中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#表達式樹Expression怎么創建

發布時間:2021-12-27 13:59:03 來源:億速云 閱讀:277 作者:iii 欄目:開發技術

本篇內容介紹了“C#表達式樹Expression怎么創建”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

什么是表達式樹

表達式樹以樹形數據結構表示代碼,其中每一個節點都是一種表達式,比如方法調用和 x < y 這樣的二元運算等。可以對表達式樹中的代碼進行編輯和運算。 這樣能夠動態修改可執行代碼、在不同數據庫中執行 LINQ 查詢以及創建動態查詢。 表達式樹還能用于動態語言運行時 (DLR) 以提供動態語言和 .NET 之間的互操作性,同時保證編譯器編寫員能夠發射表達式樹而非 Microsoft 中間語言 (MSIL)。 這段話是來自官網( [表達式樹 (C#) | Microsoft Docs](表達式樹 (C#) | Microsoft Docs) )的定義。

在 C# 中,我們可以通過 Expression 的方式來手動創建表達式樹,比如:

[HttpGet]
public IActionResult Expression()
{
    // 查詢 年齡Age 大于 18 的元素
    Expression<Func<User,bool>> expression1 = x => x.Age > 18; 
    return Ok();
}

那么,x.Age > 18 這一表達式,它的樹狀結構是這樣的:

C#表達式樹Expression怎么創建

通過 Visual Studio 自帶的查看變量或添加監視的方式,我們可以發現其中 樹的根節點(NodeType)是 GreaterThan,左節點(Left)是 x.Age,右節點(Right)是 18。所以由此就可以大概畫出樹狀結構。

C#表達式樹Expression怎么創建

最后,通過這種樹狀結構,C# 就可以幫我們將表達式編譯成具體的 SQL 執行語句。

如果想更清晰的查看表達式樹的結構,可以 nuget 一個包( ExpressionTreeToString ),將表達式結構轉換成字符串

PM> Install-Package ZSpitz.Util -Version 0.1.116
Expression<Func<User, bool>> expression = u => u.Age >= 18;
var treeStr = expression.ToString("Object notation", "C#");

// 輸出為下面字符串
var u = new ParameterExpression {
    Type = typeof(User),
    IsByRef = false,
    Name = "u"
};

new Expression<Func<User, bool>> {
    NodeType = ExpressionType.Lambda,
    Type = typeof(Func<User, bool>),
    Parameters = new ReadOnlyCollection<ParameterExpression> {
        u
    },
    Body = new BinaryExpression {
        NodeType = ExpressionType.GreaterThanOrEqual,
        Type = typeof(bool),
        Left = new MemberExpression {
            Type = typeof(int),
            Expression = u,
            Member = typeof(User).GetProperty("Age")
        },
        Right = new ConstantExpression {
            Type = typeof(int),
            Value = 18
        }
    },
    ReturnType = typeof(bool)
}

Expression 和 Func 的區別

  • Expression 存儲了運算邏輯,可以將其保存成抽象語法樹(AST),可以在運行時動態獲取運算邏輯。

  • Func 只是存儲了結果,無法保存成語法樹,也無法動態獲取運算邏輯。

所以,在 EFCore 中,使用表達式對數據庫數據進行查詢中,我們應該選擇 Expression 而不是 Func,因為使用了 Func ,實際上并無法將 Func 中的表達式轉換成 SQL,而是在將所有數據加載到內存后,在內存中在過濾 Func 中的條件。

簡單來說就是,此時要篩選 User 表中年齡大于18的數據,可以有這兩種寫法

// 這種寫法,實際生成的 SQL 語句, 大概是這樣的 SELECT * FROM User as T WHERE T.age > 18
Expression<Func<User,bool>> expression1 = x => x.Age > 18;
dbContext.User.Where(expression1).toList();

// 而這種, 生成的語句是這樣的 SELECT * FROM User, 然后將 User 表中所有數據加載到內存中后, 在進行 age > 18 的過濾
Func<User, bool> func1 = x => x.Age > 18;
dbContext.User.Where(func1).toList();

通過代碼創建表達式樹

  • ParameterExpression

  • BinaryExpression

  • MethodCallExpression

  • ConstantExpression

這些類幾乎都沒有提供構造方法,而且所有的屬性都幾乎只是只讀。因此我們一般不會直接創建這些類的實例,而是調用 Expression 類的 Parameter、MakeBinary、Call、Constant等靜態方法來生成,這些靜態方法我們一般稱作創建表達式樹的工廠方法,而屬性則通過方法參數類設置。

動態將表達式:u => u.Age >= 18; 通過代碼構建出來

一般構建步驟:

  • 先創建 ParameterExpression

  • 接著由里到外逐步構建

    • 先左節點(Left)

    • 后右節點(Right)

    • 接著Body節點

  • 將其拼接成 Expression

public IActionResult GetUserByManualExpression()
{
    ParameterExpression parameterExpression = Expression.Parameter(type:typeof(User), name: "u");
    ConstantExpression right = Expression.Constant(18);
    MemberExpression left = Expression.MakeMemberAccess(parameterExpression, member: typeof(User).GetProperty("Age"));
    BinaryExpression body = Expression.GreaterThanOrEqual(left, right);

    Expression<Func<User, bool>> expression = Expression.Lambda<Func<User, bool>>(body, parameters: parameterExpression);

    var data = _userService.GetUsers(expression);

    return Ok(new
    {
        code = 200,
        msg = "OK",
        data
    });
}

“C#表達式樹Expression怎么創建”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

四子王旗| 和平区| 惠东县| 宜宾市| 松潘县| 郓城县| 建瓯市| 兴和县| 兴宁市| 应用必备| 岗巴县| 昌乐县| 石狮市| 高州市| 东乡族自治县| 当阳市| 乌鲁木齐市| 通州市| 伊川县| 柳江县| 黎平县| 塔城市| 峨山| 萨嘎县| 泸州市| 郧西县| 滁州市| 七台河市| 承德市| 仁布县| 青田县| 荃湾区| 曲靖市| 牡丹江市| 石林| 湖州市| 叶城县| 平潭县| 湄潭县| 临武县| 绥阳县|