您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關LINQ查詢表達式如何利用c# 進行構(gòu)建,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
最近工作中遇到一個這樣的需求:在某個列表查詢功能中,可以選擇某個數(shù)字列(如商品單價、當天銷售額、當月銷售額等),再選擇 小于或等于
和 大于或等于
,再填寫一個待比較的數(shù)值,對數(shù)據(jù)進行查詢過濾。
如果只有一兩個這樣的數(shù)字列,那么使用 Entity Framework Core 可以這么寫 LINQ 查詢:
public Task<List<Product>> GetProductsAsync(string propertyToFilter, MathOperator mathOperator, decimal value) { var query = _context.Products.AsNoTracking(); query = propertyToFilter switch { "Amount1" when mathOperator == MathOperator.LessThanOrEqual => query.Where(x => x.Amount1 <= value), "Amount1" when mathOperator == MathOperator.GreaterThanOrEqual => query.Where(x => x.Amount1 >= value), "Amount2" when mathOperator == MathOperator.LessThanOrEqual => query.Where(x => x.Amount2 <= value), "Amount2" when mathOperator == MathOperator.GreaterThanOrEqual => query.Where(x => x.Amount2 >= value), _ => throw new ArgumentException($"不支持 {propertyToFilter} 列作為數(shù)字列查詢", nameof(propertyToFilter)) }; return query.ToListAsync(); }
如果固定只有一兩個數(shù)字列且將來也不會再擴展,這樣寫簡單粗暴,也沒什么問題。
但如果有幾十個數(shù)字列,這樣使用 swith 模式匹配的寫法就太恐怖了,代碼大量重復。很自然地,我們得想辦法根據(jù)屬性名動態(tài)創(chuàng)建 Where 方法的參數(shù)。它的參數(shù)類型是:Expression<Func<T, bool>>,是一個表達式參數(shù)。
要知道如何動態(tài)創(chuàng)建一個類似 Expression<Func<T, bool>> 類型的表達式實例,就要知道如何拆解表達式樹。
對于本示例,以 x => x.Amount1 <= value 表達式實例為例,它的表達式樹是這樣的:
然后我們可以按照此表達式樹結(jié)構(gòu)來構(gòu)建我們的 LINQ 表達式:
public Task<List<Product>> GetProductsAsyncV2(string propertyToFilter, MathOperator mathOperator, decimal value) { var query = _context.Products.AsNoTracking(); var paramExp = Expression.Parameter(typeof(Product)); var memberExp = Expression.PropertyOrField(paramExp, propertyToFilter); var valueExp = Expression.Constant(value); var compareExp = mathOperator == MathOperator.LessThanOrEqual ? Expression.LessThanOrEqual(memberExp, valueExp) : Expression.GreaterThanOrEqual(memberExp, valueExp); var lambda = Expression.Lambda<Func<Product, bool>>(compareExp, paramExp); return query.Where(lambda).ToListAsync(); }
每個 Expression.XXX 靜態(tài)方法返回的都是一個以 Expression 為基類的實例,代表一個表達式。不同的表達式又可以組成一個新的表達式,直到得到我們需要的 Lambda 表達式。這樣就形成了一種樹形結(jié)構(gòu),我們稱為表達式樹。知道如何把一個最終的查詢表達式拆解成表達式樹,我們就容易動態(tài)構(gòu)建此查詢表達式。
得到一個表達式后,我們還可以動態(tài)編譯并調(diào)用該表達式,比如上面示例得到的 lambda 變量,是一個Expression<Func<Product, bool>> 類型,調(diào)用其 Compile 方法,可以得到 Func<Product, bool> 類型的委托。
... var toTestProduct = new Product { Amount1 = 100, Amount2 = 200 }; Func<Product, bool> func = lambda.Compile(); var result = func(toTestProduct); Console.WriteLine($"The product's {propertyToFilter} is to {mathOperator} {value}."); // Output: The product's Amount1 is LessThanOrEqual to 150.
關于LINQ查詢表達式如何利用c# 進行構(gòu)建就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。