如何从几个表达式的并集组成一个表达式树
本文关键字:表达式 一个 几个 | 更新日期: 2023-09-27 17:57:44
我正在尝试构建一个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
中添加了几个表达式,这些表达式将它们"或"在一起。例如,如果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.中组成表达式的理解
我还需要确保树还没有被评估,这样我就可以对数据库进行过滤。这意味着我需要生产实体框架4.0可以消费的东西。
我能想到的最接近的匹配是:
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;
}
但我几乎可以肯定,这将是非常低效的
试试这样的东西?我不确定我没有测试过。
Inclusive.ForEach(exp => q = q.Union(q.Where(exp)));
尽管已经有了一个可接受的答案,但我想指出的是,您可以使用谓词生成器将表达式与Or
组合。这将使它保持为对数据库的简单查询。
http://www.albahari.com/nutshell/predicatebuilder.aspx
我还没有在实体模型上测试过它,所以我不知道EF是否会支持它,但下面的方法适用于L2O。这只是Snowbear JIM编译器的代码的一个微小变化
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;
}