dynamic生成LINQ查询

我们有一个对象

public class SomeObject { public Name {get;set;} public City {get;set;} public State {get;set} //various other parameters. Let's say there's ~20 } 

是否可以在不重新编译源代码的情况下dynamic创build新的LINQ查询? 相反,查询参数来自在数据库中存储和更新的XML结构。

 var result = from i in someObj where //XML requests Name = 'Bob'...so append this where clause name = 'Bob' 

可以这样做吗?

这是一个expression式树的解决scheme:

 var param = Expression.Parameter(typeof(SomeObject), "p"); var exp = Expression.Lambda<Func<SomeObject, bool>>( Expression.Equal( Expression.Property(param, "Name"), Expression.Constant("Bob") ), param ); var query = someObj.Where(exp); 

我知道这要复杂得多,但这可能会有用。

你肯定会想看看dynamicLinq ,这将允许你定义查询条件为文本。

至于dynamic添加条件,您可以使用类似的语法为查询添加条件;

 if(CategoryIsImportant) myQuery = myQuery.Where("CategoryId=2"); 

所有你可以(相当容易)编码成你select的XML格式。

我很难根据你的问题来判断,但是在某些情况下,你不需要dynamic的Linq,只需要简单地这样做…

 var result = from o in someObj where (Name == null || o.Name == Name) && (City == null || o.City == City) && (State == null || o.State == State) select o; 

这将基本上防止在参数为空时过滤数据。 而且,由于C#中的短路行为,它仍然performance良好。

也许dynamicLinq可以帮助你:dynamicLINQ 第1部分:使用 LINQ dynamic查询库

 query = query.Where("Id = 123 And Age > 18"); 

或者你可以直接操纵你的Linq查询:

 query = query.Where(x=>x.Id == 5); 

我相信你将不得不深入expression树 。 我还没有深入到这一点,所以我不能为你创build一个示例,但我知道你可以使用expression式树来dynamic构build你的查询,然后调用.Compile(在代码中)让它可以运行。

实际上,这是build立dynamic查询和expression式树的更好的链接。 它应该给你你想要的东西,而且它是相当简洁的。 这应该成为你的一个很好的例子:)

我假设你想要引入可选的filter,这取决于你的XML的内容。 通过StriplingWarrior继续这个例子:

 var name = GetNameFromXml(); var city = GetCityFromXml(); var state = GetStateFromXml(); var result = someObj; if (name != null) result = result.Where(i => i.Name == name); if (city != null) result = result.Where(i => i.City == city); if (state != null) result = result.Where(i => i.State == state); 

这样,根据XML中实际指定的内容,您将应用任意数量的filter(从无到三)。

是的,这其实很简单:

 var name = GetBobNameFromXml(); var result = someObj.Where(i => i.Name == name); 

您也可以select是否零碎地使用标准。

 var result = someObj; var name = xmlCriteria.Name; if(!string.IsNullOrEmpty(name)) { result = result.Where(i => i.Name == name); } // follow the same pattern for city, state, etc. 

你甚至可以使用一个使用规则funcs的名字键字典的模式来避免一堆if语句。

 foreach(var criterionPair in xmlCriteria) { var value = criterionPair.Value; result = result.Where(i => propGetters[criterionPair.PropertyName](i, value)); } 

基本上,你可以沿着这些方向做很多事情。 如果你想要一个更适合你的情况的答案,你需要提供一个更具体的问题。