我正在尝试构建一个IQueryable
,它将由我的实体模型进行评估。我想传递两组lambdas并将它组合成一个更复杂的表达式树,并将其传递给数据库以供执行。
这是我到目前为止所拥有的:
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可以使用的东西。
答案 0 :(得分:3)
我能想到的最接近的匹配是:
public IQueryable<T> ApplyFilters(IQueryable<T> query)
{
IQueryable<T> q;
if (!Inclusive.Any())
q = query;
else
{
q = Enumerable.Empty<T>();
Inclusive.ForEach(exp => q = q.Union(query.Where(exp)));
}
Exclusive.ForEach(exp => q = q.Where(exp));
return q;
}
但我几乎可以肯定这会非常低效
答案 1 :(得分:0)
尝试这样的事情? 我不确定我没有测试过它。
Inclusive.ForEach(exp => q = q.Union(q.Where(exp)));
答案 2 :(得分:0)
即使已经有一个已接受的答案,我想指出你可以使用谓词构建器将表达式与Or
结合起来。这将使其成为对数据库的简单查询。
答案 3 :(得分:0)
我还没有在我的实体模型上测试它,所以我不知道它是否会得到EF的支持,但以下是适用于L2O的。这只是 Snowbear JIM-compiler 的代码略有变化:
public IQueryable<T> ApplyFilters(IQueryable<T> query)
{
Exclusive.ForEach(exp => query = query.Where(exp));
if (Inclusive.Count == 0)
{
return query;
}
IQueryable<T> q = Enumerable.Empty<T>().AsQueryable<T>();
Inclusive.ForEach(exp => q = q.Union(query.Where(exp)));
return q;
}