我希望使用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")
无效。
基本上,这就是我要做的事情:
foreach(var name in names)
{
items = items.Where(p => p.Name == name);
}
答案 0 :(得分:13)
假设您要编写实现关键字样式搜索的LINQ to SQL或Entity Framework查询。换句话说,一个返回描述包含一些或全部给定关键字集的行的查询......
理想的方法是动态构造一个执行基于或的谓词的lambda表达式树。
在推动您手动构建表达式树的所有事情中,动态谓词的需求是典型业务应用程序中最常见的。幸运的是,可以编写一组简单且可重用的扩展方法,从根本上简化此任务。这是我们的 PredicateBuilder 类...
的作用
答案 1 :(得分:10)
您可以使用.Union()
返回满足任何条件的结果。
var results = items.Where(p => p.FirstName == "John")
.Union(items.Where(p => p.LastName == "Smith"));
这不如使用||
运算符。从您的编辑中不清楚为什么这不起作用。
答案 2 :(得分:8)
听起来你的名字白名单只在运行时才知道。也许试试这个:
string[] names = new string[] {"John", "foo", "bar"};
var matching = items.Where(x => names.Contains(x.Name));
答案 3 :(得分: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);
答案 4 :(得分:0)
您无法使Where
子句动态化,但您可以动态创建传递给它的Lambda Expression。创建正确的Expression,编译它并将生成的lambda表达式作为参数传递给Where子句。
修改强>
好的,似乎您可以跳过必须手动创建表达式的部分,并可以使用PredicateBuilder,因为AS-CII已经回答过了。