有选择地从LINQ表达式树中的where子句中删除

时间:2008-11-28 12:51:34

标签: .net linq

从以下LINQ查询开始:

from a in things  
where a.Id == b.Id &&  
a.Name == b.Name &&  
a.Value1 == b.Value1 &&  
a.Value2 == b.Value2 &&  
a.Value3 == b.Value3  
select a;

如何删除(在运行时)where子句中的一个或多个条件,以获取类似于以下内容的查询:

from a in things  
where a.Id == b.Id &&  
a.Name == b.Name &&  
a.Value2 == b.Value2 &&  
a.Value3 == b.Value3  
select a;

或者

from a in things  
where 
a.Name == b.Name &&  
a.Value3 == b.Value3  
select a;

3 个答案:

答案 0 :(得分:6)

我没有尝试改变现有的where子句,而是将其重构为:

from a in things  
where a.Id == b.Id 
where a.Name == b.Name 
where a.Value1 == b.Value1
where a.Value2 == b.Value2
where a.Value3 == b.Value3  
select a;

然后变成:

things.Where(a => a.Id == b.Id)
      .Where(a => a.Name == b.Name)
      .Where(a => a.Value1 == b.Value1)
      .Where(a => a.Value2 == b.Value2)
      .Where(a => a.Value1 == b.Value3);

现在应该相当清楚如何继续 - 将调用条件化为Where:

IQueryable<Whatever> query = things;
if (useId) {
    query = query.Where(a => a.Id == b.Id);
}
query = query.Where(a => a.Name == b.Name);
if (checkValue1) {
    query = query.Where(a => a.Value1 == b.Value1);
}
// etc

答案 1 :(得分:1)

这也可能是另一种方法;

bool executeValue1Condition = true;
bool executeValue2Condition = true;
bool executeValue3Condition = true;

var q = from a in things  
where a.Id == b.Id &&  
a.Name == b.Name &&  
(a.Value1 == b.Value1 || executeValue1Condition) &&  
(a.Value2 == b.Value2 || executeValue2Condition) &&  
(a.Value3 == b.Value3 || executeValue3Condition) 
select a;

executeValue1Condition = false;
q = q.Select(i => i);

此外,通过使用此方法,您可以在执行查询后更改条件,但当然可以通过新执行来更改。

答案 2 :(得分:0)

尝试分开事物。首先将where条件与查询的其余部分隔离,然后处理它并使用标准查询方法而不是内置的语法糖。例如:

     IQueryable<MyClass> things = null;
     MyClass b = new MyClass();

     Expression<Func<MyClass, bool>> whereExp = a => a.Id == b.Id && a.Name == b.Name;
     // process where expression here. it's just an expression tree. traverse it and
     // remove nodes as desired.
     var result = things.Where(whereExp).Select(a => a);

实现这一目标的另一个更简单的方法是不是从完整表达开始并删除东西,而是从部分组成一个。例如:

IQueryable<MyClass> things = null;
MyClass b = new MyClass();

Expression<Func<MyClass, bool>> whereExp;
Expression<Func<MyClass, bool>> exp1 = a => a.Id == b.Id;
Expression<Func<MyClass, bool>> exp2 = a => a.Name == b.Name;
whereExp = Expression.Lambda<Func<MyClass, bool>>(Expression.And(exp1, exp2), Expression.Parameter(typeof(MyClass), "a"));

var result = things.Where(whereExp).Select(a => a);