假设我们需要应用几个条件来选择一个名为“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:动态编写表达式谓词
答案 0 :(得分:5)
你可以使用带有静态方法的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而不是编译表达式
答案 1 :(得分:2)
对于OR
,您有两种选择:
Union
/ Concat
Expression
第二个更靠近.Where(x => {a} || {b})
。
如果您使用的是LINQ-to-SQL,则可以使用Expression.Invoke
组合多个单独的lambda表达式(see this answer) - 但是,Entity Framework中不支持此功能。在EF中,您必须使用Expression.OrElse
将整个表达式构建为单个块;例如here或here。