<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          或許你還不知道如何動態(tài)構(gòu)建LINQ查詢表達(dá)式?

          共 1067字,需瀏覽 3分鐘

           ·

          2020-12-04 13:24

          最近工作中遇到一個這樣的需求:在某個列表查詢功能中,可以選擇某個數(shù)字列(如商品單價、當(dāng)天銷售額、當(dāng)月銷售額等),再選擇?小于或等于?和?大于或等于?,再填寫一個待比較的數(shù)值,對數(shù)據(jù)進(jìn)行查詢過濾。

          如果只有一兩個這樣的數(shù)字列,那么使用 Entity Framework Core 可以這么寫 LINQ 查詢:

          public Task> 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?模式匹配的寫法就太恐怖了,代碼大量重復(fù)。很自然地,我們得想辦法根據(jù)屬性名動態(tài)創(chuàng)建?Where?方法的參數(shù)。它的參數(shù)類型是:Expression>,是一個表達(dá)式參數(shù)。

          要知道如何動態(tài)創(chuàng)建一個類似?Expression>?類型的表達(dá)式實例,就要知道如何拆解表達(dá)式樹。

          對于本示例,以?x => x.Amount1 <= value?表達(dá)式實例為例,它的表達(dá)式樹是這樣的:

          然后我們可以按照此表達(dá)式樹結(jié)構(gòu)來構(gòu)建我們的 LINQ 表達(dá)式:

          public Task> 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.Lambdabool>>(compareExp, paramExp);

          return query.Where(lambda).ToListAsync();
          }

          每個?Expression.XXX?靜態(tài)方法返回的都是一個以?Expression?為基類的實例,代表一個表達(dá)式。不同的表達(dá)式又可以組成一個新的表達(dá)式,直到得到我們需要的 Lambda 表達(dá)式。這樣就形成了一種樹形結(jié)構(gòu),我們稱為表達(dá)式樹。知道如何把一個最終的查詢表達(dá)式拆解成表達(dá)式樹,我們就容易動態(tài)構(gòu)建此查詢表達(dá)式。

          得到一個表達(dá)式后,我們還可以動態(tài)編譯并調(diào)用該表達(dá)式,比如上面示例得到的?lambda?變量,是一個Expression>?類型,調(diào)用其?Compile?方法,可以得到?Func?類型的委托。

          ...

          var toTestProduct = new Product { Amount1 = 100, Amount2 = 200 };

          Funcbool> 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.

          你可以通過研究?Expression?類來了解更多動態(tài)構(gòu)建表達(dá)式的方法。

          動態(tài)構(gòu)建 LINQ 表達(dá)式對于不能在編譯時建立查詢,只能在運行時建立查詢的場景很有用。但它的缺點也很明顯,不易維護、不易閱讀、不易調(diào)試。如果最終的表達(dá)式執(zhí)行出錯,很難通過調(diào)試來發(fā)現(xiàn)具體是構(gòu)建中的那一步寫錯了,只能憑自己的理解和經(jīng)驗查找錯誤。所以,如非必須,一般不推薦動態(tài)構(gòu)建 LINQ 查詢表達(dá)式。

          回復(fù)?【關(guān)閉】學(xué)關(guān)
          回復(fù)?【實戰(zhàn)】獲取20套實戰(zhàn)源碼
          回復(fù)?【被刪】學(xué)
          回復(fù)?【訪客】學(xué)
          回復(fù)?【小程序】學(xué)獲取15套【入門+實戰(zhàn)+賺錢】小程序源碼
          回復(fù)?【python】學(xué)微獲取全套0基礎(chǔ)Python知識手冊
          回復(fù)?【2019】獲取2019 .NET 開發(fā)者峰會資料PPT
          回復(fù)?【加群】加入dotnet微信交流群

          臥槽:微軟又推出新的開源網(wǎng)站!


          臥槽:第一次見這么牛x的網(wǎng)站?


          瀏覽 50
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  九九视频国产 | 日韩有码日韩无码 | 国产熟女视频 | 日韩欧美国产一级片 | 日韩无码一二三 |