Linq2SQL“或/和”运算符(ANDed / ORed条件)

假设我们需要应用几个条件来选择一个名为“Things”的表(未知计数和性质)

如果条件已知,我们可以写

db.Things.Where(t=>foo1 && foo2 || foo3); 

但是如果我们必须以编程方式构建Where条件,我可以想象我们如何应用ANDed条件

 IQuerable DesiredThings = db.Things.AsQuerable(); foreach (Condition c in AndedConditions) DesiredThings = DesiredThings.Where(t => GenerateCondition(c,t)); 

ORed条件怎么样? 注意:我们不想执行union,unique或任何其他代价高昂的操作,我们希望生成一个查询,好像我们将它写成ad-hock

提前致谢。


加成:

PredicateBuilder:动态编写表达式谓词

您可以将Expression类与静态方法一起使用来运行它。

下面的代码是创建一个委托,它接受一个名为int的类型的参数。 它从buttom到top读取所以有问题的行是:

 var method = LambdaExpression.Lambda(orExp, Expression.Parameter(typeof(int), "value")); 

方法的主体将参数的值与对foo类型的新创建对象的方法Bar的调用进行比较

 var exp2 = Expression.Equal(Expression.Parameter(typeof(int), "value"), Expression.Property(Expression.New(typeof(Foo).GetConstructor(new Type[] { })), "Bar")); 

然后它创建一个类似的表达式或者是它们

  var orExp = Expression.OrElse(exp1, exp2); 

最后一件事是调用编译。 该调用生成一个可以在where方法调用中使用的委托。

希望它有助于我不能100%确定表达式从参数获取值

 var exp1 = Expression.Equal(Expression.Parameter(typeof(int),"value"), Expression.Property(Expression.New(typeof(Bar).GetConstructor(new Type[] { })), "Foo")); var exp2 = Expression.Equal(Expression.Parameter(typeof(int), "value"), Expression.Property(Expression.New(typeof(Foo).GetConstructor(new Type[] { })), "Bar")); var orExp = Expression.OrElse(exp1, exp2); var method = LambdaExpression.Lambda(orExp, Expression.Parameter(typeof(int), "value")); method.Compile(); 

如果您需要将LambdaExpression转换为与二进制代码不同的内容(例如,转换为SQL语句),您可能希望查看调用invoke而不是编译表达式

对于OR ,您有两种选择:

  • 使用Union / Concat
  • 在代码中编写Expression

第二个更接近.Where(x => {a} || {b})

如果您使用的是LINQ-to-SQL,则可以使用Expression.Invoke组合多个单独的lambda表达式( 请参阅此答案 ) – 但是,Entity Framework中不支持此function。 在EF中,您必须使用Expression.OrElse将整个表达式构建为单个块; 例如这里或这里 。