【发布时间】:2011-05-26 16:43:46
【问题描述】:
我正在尝试构建一个IQueryable,它将由我的实体模型进行评估。我想向它传递两组 lambda,让它将所有内容组合成一个更复杂的表达式树,然后传递给数据库执行。
这是我目前所拥有的:
public class FilterManager<T>
{
public List<Expression<Func<T, bool>>> Inclusive { get; set; }
public List<Expression<Func<T, bool>>> Exclusive { get; set; }
public IQueryable<T> ApplyFilters(IQueryable<T> query)
{
var q = query;
Exclusive.ForEach(exp => q = q.Where(exp)); //works fine
Inclusive.ForEach(exp => /* ??? */);
return q;
}
//ctor, etc.
}
这里的想法是我将几个表达式添加到Inclusive,它们将它们“Ors”在一起。例如,如果T 是int,则代码:
fm.Inclusive.Add(x => x > 1);
fm.Inclusive.Add(y => y < 5);
query = fm.ApplyFilters(query);
应该有相同的结果集:
query = query.Where(z => z > 1 || z < 5);
如何在没有第三方工具(例如 PredicateBuilder)的情况下让 Inclusive 工作?第三方工具通常很好,但我想加深对如何在 .NET 中编写表达式的理解。
我还需要确保尚未评估树,以便我可以对数据库进行过滤。这意味着我需要生成 Entity Framework 4.0 可以使用的东西。
【问题讨论】:
-
复制:stackoverflow.com/questions/5430996/… ? (我的回答显示了 2 种内联表达式的方法;IMO 首选“访问者”版本)
-
@Marc - 谢谢,我现在正在阅读您的链接。伙计,当您深入研究 ExpressionRewriter 时,就会有很多代码。但这适用于
OrElse类型的行为吗?这里的问题是关于AndAlso,我觉得更符合我的Exclusive设置。 -
要记住的重要一点是,在您的示例中,每个 x=>x>1 和 x=>x不同的变量。想象一下它们被称为 x1 和 x2。如果你天真地将它们组合成第三个,那么你会得到 x3=>x1>1||x2按引用,而不是按名称。这些名称基本上被忽略了。
-
@Eric - 是的,如果我不清楚,对不起。我的意思是这两个 sn-ps 应该返回相同的结果集,而不必具有相同的内部行为或使用相同的变量。我重命名了变量以使其更清晰。
-
@Marc - 感谢您的链接,我认为您的访问者代码绝对是正确的方法。如果这个简单的版本不能破解它,我将使用你的代码。
标签: c# .net-4.0 entity-framework-4 linq-to-entities expression-trees