如何从多个表达式的并集组成表达式树?

发布于 2024-11-09 21:30:07 字数 1171 浏览 0 评论 0原文

我正在尝试构建一个 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 中,将它们“或”在一起。例如,如果 Tint,则代码:

fm.Inclusive.Add(x => x > 1);
fm.Inclusive.Add(y => y < 5);

query = fm.ApplyFilters(query);

应具有与以下内容相同的结果集:

query = query.Where(z => z > 1 || z < 5);

How can I get Inclusive to work without Third - PredicateBuilder 等第三方工具?第三方工具通常很好,但我想提高对如何在 .NET 中编写表达式的理解。

我还需要确保树不会被评估,以便我可以对数据库进行过滤。这意味着我需要生成 Entity Framework 4.0 可以使用的东西。

I'm trying to construct an IQueryable which will be evaluated by my entity model. I want to pass it two groups of lambdas and have it compose everything into a more complex expression tree, which is passed on to the database for execution.

Here's what I have so far:

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.
}

The idea here is that I add several Expressions to Inclusive, which "Ors" them together. For example, if T is an int, the code:

fm.Inclusive.Add(x => x > 1);
fm.Inclusive.Add(y => y < 5);

query = fm.ApplyFilters(query);

should have the same result set as:

query = query.Where(z => z > 1 || z < 5);

How can I get Inclusive to work without third-party tools such as PredicateBuilder? Third-party tools are usually fine, but I'd like to improve my understanding of how to compose expressions in .NET.

I also need to make sure that the tree won't be evaluated yet, so that I can do the filtering on the database. That means I'll need to produce something Entity Framework 4.0 can consume.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请你别敷衍 2024-11-16 21:30:08

尝试这样的事情吗?
我不确定我没有测试过。

Inclusive.ForEach(exp => q = q.Union(q.Where(exp)));

Try something like this?
I'm not sure I haven't tested it.

Inclusive.ForEach(exp => q = q.Union(q.Where(exp)));
智商已欠费 2024-11-16 21:30:08

尽管已经有了一个可接受的答案,但我想指出您可以使用谓词构建器将表达式与 Or 组合起来。这将使其保留为对数据库的简单查询。

http://www.albahari.com/nutshell/predicatebuilder.aspx

Even though there's already an accepted answer, I would like to point out you can use predicate builder to combine the expressions with an Or. This will keep it as a simple query to the database.

http://www.albahari.com/nutshell/predicatebuilder.aspx

抱着落日 2024-11-16 21:30:08

我还没有在我的实体模型上测试过它,所以我不知道 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;
}

I haven't tested it on my entity model yet, so I don't know if it will be supported by EF, but the following works for L2O. It's just a slight change from Snowbear JIM-compiler's code:

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;
}
剑心龙吟 2024-11-16 21:30:07

我能想到的最接近的匹配是这样的:

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;
}

但我几乎可以肯定这会非常低效

The closest match I can think of is this:

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;
}

But I'm almost sure that this will be very inefficient

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文