2010-12-08 39 views
12

我期待使用LINQ做多,其中在收集类似动态LINQ和条件

IEnumerable<Object> items; 
items.Where(p => p.FirstName = "John"); 
items.Where(p => p.LastName = "Smith"); 

除了而非使用多个AND条件(如本例中)的条件下,我想有多个OR条件。

编辑 对不起,澄清我不知道我将有多少这些条件使

items.Where(p => p.FirstName = "John" || p => p.LastName = "Smith") 

将无法​​正常工作。

基本上,这里是我想要做什么:

回答

7

这听起来像你的名字的白名单仅在运行时知道。也许试试这个:

string[] names = new string[] {"John", "foo", "bar"}; 

var matching = items.Where(x => names.Contains(x.Name)); 
+0

It's一直是我的超级有用的,因为我已经在看LINQ的动态库只是为了做到这一点。谢谢! – xleon 2015-06-24 01:16:12

13

使用PredicateBuilder

假设你想要写一个LINQ to SQL的或实现一个关键词的搜索式的实体框架查询。换句话说,查询返回行其描述包含部分或全部给定一组关键词的...

理想的方法是动态地构建执行基于谓词lambda表达式树。

在推动您手动构建表达式树的所有事情中,动态谓词的需求是典型业务应用程序中最常见的。幸运的是,可以编写一套简单且可重用的扩展方法,从根本上简化了这一任务。这是我们PredicateBuilder类的角色......

+0

干得好,但不适用于LINQ to Entities和实体框架(6):LINQ to Entities不支持LINQ表达式节点类型“Invoke”。 – 2016-12-13 10:51:20

10

您可以使用.Union()返回满足任何条件的结果。

var results = items.Where(p => p.FirstName == "John") 
    .Union(items.Where(p => p.LastName == "Smith")); 

这比使用||算子差。从你的编辑中不清楚为什么这不起作用。

+0

使用工会绝对是一个聪明的把戏! +1。 – Steven 2010-12-08 19:05:09

0

您不能使Where子句变为动态,但可以动态创建传递给它的Lambda表达式。创建正确的Expression,编译它并将生成的lambda表达式作为参数传递给Where子句。

编辑:

好了,好像你可以跳过,你必须手动创建的表达可以用PredicateBuilder它的一部分,已经被AS-CII回答。

2
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
     this IEnumerable<Expression<Func<T, bool>>> filters) 
    { 
     Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault(); 
     if (firstFilter == null) 
     { 
      Expression<Func<T, bool>> alwaysTrue = x => true; 
      return alwaysTrue; 
     } 

     var body = firstFilter.Body; 
     var param = firstFilter.Parameters.ToArray(); 
     foreach (var nextFilter in filters.Skip(1)) 
     { 
      var nextBody = Expression.Invoke(nextFilter, param); 
      body = Expression.OrElse(body, nextBody); 
     } 
     Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param); 
     return result; 
    } 

然后,后来:

List<Expression<Func<Person, bool>>> filters = names 
    .Select<string, Expression<Func<Person, bool>>>(name => 
    p => p.Name == name 
).ToList(); 

Expression<Func<Person, bool>> filterOfOrs = filters.OrTheseFiltersTogether(); 

query = query.Where<Person>(filterOfOrs); 
+0

调用不支持LINQ到实体:( – yonexbat 2011-08-28 18:57:32