2

假设我们需要应用几个条件来从名为“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 条件呢?注意:我们不想执行联合、唯一或任何其他昂贵的操作,我们希望生成一个查询,就好像我们临时编写它一样

提前致谢。


添加:

PredicateBuilder:动态组合表达式谓词

4

2 回答 2

5

您可以使用带有静态方法的 Expression 类来执行它的运行时间。

下面的代码用于创建一个委托,该委托采用一个称为 int 类型值的参数。它从底部到顶部读取,因此有问题的行是:

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"));

然后它会创建一个类似的表达式和 or's them

        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 语句),您可能想查看调用的调用而不是编译表达式

于 2009-09-20T18:29:00.417 回答
3

对于OR,您有两种选择:

  • 使用Union/Concat
  • 写入Expression代码

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

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

于 2009-09-20T18:28:00.203 回答