簡體   English   中英

使用表達式樹的LINQ動態查詢

[英]LINQ Dynamic Query using Expression Tree

我試圖使自己熟悉“表達樹”,並且碰壁。 我希望能夠動態地創建LINQ to XML查詢,因此我試圖使自己熟悉表達式樹。 我從一個希望能夠動態生成的簡單LINQ to XML語句開始:

        // sample data
        var sampleData = new XElement("Items",
            new XElement("Item", new XAttribute("ID", 1)),
            new XElement("Item", new XAttribute("ID", 2)),
            new XElement("Item", new XAttribute("ID", 3))
            );

        // simple example using LINQ to XML (hard-coded)
        var resultsStatic = from item in sampleData.Elements("Item")
                            where item.Attribute("ID").Value == "2"
                            select item;

        // trying to recreate the above dynamically using expression trees
        IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable<XElement>();
        ParameterExpression alias = Expression.Parameter(typeof(XElement), "item");
        MethodInfo attributeMethod = typeof(XElement).GetMethod("Attribute", new Type[] { typeof(XName) });
        PropertyInfo valueProperty = typeof(XAttribute).GetProperty("Value");
        ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");
        Expression methodCall = Expression.Call(alias, attributeMethod, new Expression[] { attributeParam });
        Expression propertyAccessor = Expression.Property(methodCall, valueProperty);
        Expression right = Expression.Constant("2");
        Expression equalityComparison = Expression.Equal(propertyAccessor, right);
        var resultsDynamic = queryableData.Provider.CreateQuery(equalityComparison);

我在調用CreateQuery時遇到的錯誤是“參數表達式無效”。 equityComparison的調試視圖顯示為'(.Call $ item.Attribute($ ID))。Value ==“ 2”'。 有人可以識別我在做什么嗎?

為了更好地了解發生了什么,請始終從所需查詢的方法語法開始。 在您的情況下,如下所示(我通常包括類型,盡管通常我會使用var ):

IQueryable<XElement> queryableData = sampleData.Elements("Item").AsQueryable();
IQueryable<XElement> queryStatic = queryableData
    .Where((XElement item) => item.Attribute("ID").Value == "2");

現在,讓我們看看您有什么。

首先, attributeParam變量

ParameterExpression attributeParam = Expression.Parameter(typeof(XName), "ID");

從靜態查詢中可以看到,屬性名稱沒有lambda參數-唯一受支持(和必需)的參數是item (在您的代碼中由alias變量表示)。 因此,這應該是XName類型的ConstantExpression ,其值為“ ID”:

var attributeParam = Expression.Constant((XName)"ID");

第二, equalityComparison變量。 它只包含item.Attribute("ID").Value == "2"表達式。 但是Where方法需要Expression<Func<XElement, bool>> ,因此您必須使用equalityComparison作為主體和alias作為參數來創建這樣的類:

var predicate = Expression.Lambda<Func<XElement, bool>>(equalityComparison, alias);

最后,您必須調用Where方法。 您可以直接執行以下操作:

var queryDynamic = queryableData.Where(predicate);

或動態地:

var whereCall = Expression.Call(
    typeof(Queryable), "Where", new Type[] { queryableData.ElementType },
    queryableData.Expression, Expression.Quote(predicate));
var queryDynamic = queryableData.Provider.CreateQuery(whereCall);

您可以查看所使用的Expression方法文檔,以進一步了解它們的作用。

Linq to XML在內存中工作,這意味着您無需使用表達式樹,只需使用Enumerable擴展方法即可。 使您的代碼更簡單易讀!!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM