LINQ lambda表达式追加OR语句

时间:2012-11-19 21:00:35

标签: c# linq c#-3.0

如果我想在查询中附加AND语句,我可以这样做:

query = query.Where(obj=>obj.Id == id);

if(name.HasValue)
  query = query.Where(obj=>obj.Name == name);

它会给我:

query.Where(obj=>obj.Id == id && obj.Name == name)

如何附加导致以下内容的OR语句:

query.Where(obj=>obj.Id == id || obj.Name == name)

5 个答案:

答案 0 :(得分:6)

你不能本地做。但是,您可以在运行之前使用PredicateBuilder撰写查询,并且它支持OR。

var predicate = PredicateBuilder.False<Product>();
predicate = predicate.Or (obj=>obj.Id == id);
if(name.HasValue)  predicate = predicate.Or (obj=>obj.Name == name);

return query.Where(predicate);

答案 1 :(得分:3)

如果我没有遗漏某些内容,那就是这样:

query.Where(obj=>obj.Id == id || (obj.Name == name && name.HasValue))

您可能想要阅读这个问题(我的问题......)并回答更复杂的情况:
How to filter IEnumerable based on an entity input parameter

答案 2 :(得分:0)

我只是把它构建成一个条件:

if (name.HasValue)
    query = query.Where(obj=>obj.Id == id && obj.Name == name);
else
    query = query.Where(obj=>obj.Id == id);

答案 3 :(得分:0)

我会使用gdoron的解决方案,但如果对于更大的查询集似乎不太实际,那么包含set操作的稍微复杂的解决方案可能对您有所帮助:

var queryById = query.Where(obj => obj.Id == id);
var queryByName = query.Where(obj => obj.Name == name);
query = queryById.Union(queryByName);

如果原始查询包含重复项,则会变得更加困难。

另一种方法可能是使用Expression来制定您的查询。您可以在执行之前修改表达式树,以便可以向Where子树添加更多条件。这是一个整批的工作,对于99.9%(粗略估计:)的案例来说是一种过度杀伤。

答案 4 :(得分:0)

部分问题在于您过度编写原始查询。你的OR操作相当于:

subquery1 = query.Where(obj=>obj.Id == id);
subquery2 = query.Where(obj=>obj.Name == name);
query = subquery1.Concat(subquery2).Distinct();

正如你所看到的那样,这也变得相当笨拙,但是如果你打算做这个形式,那么你必须保持原始序列,这样你就可以得到处理方程的左右两边然后你需要确保重复删除。

而不是所有这些,我会尝试使用lambdas动态构建条件语句,例如。

我实际上并没有这样做,但是这样的事情应该有效。

var cond = obj=>obj.Id == id;

...

// need an or
cond = obj=>cond(obj) || obj.Name == name;

query = query.Where(obj=>cond(obj));

希望这会给你一个想法。

相关问题