[英]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.