1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        [C#.NET 拾遺補(bǔ)漏]13:動態(tài)構(gòu)建LINQ查詢表達(dá)式

        共 1067字,需瀏覽 3分鐘

         ·

        2020-11-29 04:04


        最近工作中遇到一個這樣的需求:在某個列表查詢功能中,可以選擇某個數(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ù)字列且將來也不會再擴(kuò)展,這樣寫簡單粗暴,也沒什么問題。

        但如果有幾十個數(shù)字列,這樣使用?swith?模式匹配的寫法就太恐怖了,代碼大量重復(fù)。很自然地,我們得想辦法根據(jù)屬性名動態(tài)創(chuàng)建?Where?方法的參數(shù)。它的參數(shù)類型是:Expression>,是一個表達(dá)式參數(shù)。

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

        對于本示例,以?x => x.Amount1 <= value?表達(dá)式實(shí)例為例,它的表達(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?為基類的實(shí)例,代表一個表達(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á)式對于不能在編譯時建立查詢,只能在運(yùn)行時建立查詢的場景很有用。但它的缺點(diǎn)也很明顯,不易維護(hù)、不易閱讀、不易調(diào)試。如果最終的表達(dá)式執(zhí)行出錯,很難通過調(diào)試來發(fā)現(xiàn)具體是構(gòu)建中的那一步寫錯了,只能憑自己的理解和經(jīng)驗(yàn)查找錯誤。所以,如非必須,一般不推薦動態(tài)構(gòu)建 LINQ 查詢表達(dá)式。


        往期精彩回顧




        【推薦】.NET Core開發(fā)實(shí)戰(zhàn)視頻課程?★★★

        .NET Core實(shí)戰(zhàn)項目之CMS 第一章 入門篇-開篇及總體規(guī)劃

        【.NET Core微服務(wù)實(shí)戰(zhàn)-統(tǒng)一身份認(rèn)證】開篇及目錄索引

        Redis基本使用及百億數(shù)據(jù)量中的使用技巧分享(附視頻地址及觀看指南)

        .NET Core中的一個接口多種實(shí)現(xiàn)的依賴注入與動態(tài)選擇看這篇就夠了

        10個小技巧助您寫出高性能的ASP.NET Core代碼

        用abp vNext快速開發(fā)Quartz.NET定時任務(wù)管理界面

        在ASP.NET Core中創(chuàng)建基于Quartz.NET托管服務(wù)輕松實(shí)現(xiàn)作業(yè)調(diào)度

        現(xiàn)身說法:實(shí)際業(yè)務(wù)出發(fā)分析百億數(shù)據(jù)量下的多表查詢優(yōu)化

        關(guān)于C#異步編程你應(yīng)該了解的幾點(diǎn)建議

        C#異步編程看這篇就夠了


        瀏覽 57
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            无吗视频在线观看 | 欧美操网| 欧美综合77777色婷婷 | 岳让我挺进去呻吟声小说 | 午夜成人福利在线观看 | 久射久 | 性一乱一交一交一视频 | 好多水好爽小荡货白洁 | 小黄片国产 | 天天爽夜夜爽AA片免费 |