PredicateBuilder 多个 AND OR 的问题

发布于 2024-10-29 13:53:07 字数 2148 浏览 3 评论 0原文

我有一个关于 PredicateBuilder 的问题,我真的希望你能给我一些关于如何解决这个问题的建议。我将尝试解释这一点。

我的例子是人们可以根据关键字搜索产品。每个关键字都属于一个关键字组,因此一些真实数据将是:

关键字组/关键字

类型 - 链/

类型 - 手链/

颜色 - 紫色/

颜色 - 绿色

现在我想要得到以下结果:

在每个不同的关键字组之间应该有一个 OR 。 KeywordGroup 内的每个不同关键字之间应该有一个 AND。

例如,用户想要仅搜索颜色为紫色或绿色的手镯。

这个 PredicateBuilder 可以实现吗?

这是我到目前为止所拥有的:

==================================

/// <summary>
    /// Search for products
    /// </summary>
    /// <param name="itemsPerPage"></param>
    /// <returns></returns>
    public List<Product> SearchProducts(int from, int max, string sorting, List<Keyword> filter, out int totalitems) {
        try {

            var predicate = PredicateBuilder.True<Product>();
            KeywordGroup previousKeywordGroup = null;
            foreach (Keyword k in filter.OrderBy(g=>g.KeywordGroup.SortOrder)) {
                if (previousKeywordGroup != k.KeywordGroup) {
                    previousKeywordGroup = k.KeywordGroup;

                    predicate = predicate.And(p => p.Keywords.Contains(k));
                }
                else
                    predicate = predicate.Or(p => p.Keywords.Contains(k));
            }

            var products = context.Products.AsExpandable().Where(predicate);

            //var products = from p in context.Products
            //               from k in p.Keywords
            //               where filter.Contains(k)
            //               select p;

            totalitems = products.Distinct().Count();
            if (sorting == "asc")
                return products.Where(x => x.Visible == true).Distinct().Skip(from).Take(max).OrderBy(o => o.SellingPrice).ToList();
            else
                return products.Where(x => x.Visible == true).Distinct().Skip(from).Take(max).OrderByDescending(o => o.SellingPrice).ToList();
        }
        catch (Exception ex) {
            throw ex;
        }
    }

========== ======================

但它不起作用。

你能帮我一下吗?

谢谢! 丹尼尔

I've a question about the PredicateBuilder and I really hope you can give me some advice on how to solve this. I'll try to explain this.

I have the case where people can search for products based on keywords. Each keyword belongs to a keywordgroup, so some real data would be:

KeywordGroup / Keyword

Type - Chain/

Type - Bracelet/

Color - Purple/

Color - Green

Now I want to have the following results:

Between each different KeywordGroup there should be an OR.
Between each different Keyword inside a KeywordGroup there should be an AND.

So e.g., a user want's to search for only Bracelets with the colors Purlple or Green.

Is this possible with this PredicateBuilder?

This is what I have so far:

================================

/// <summary>
    /// Search for products
    /// </summary>
    /// <param name="itemsPerPage"></param>
    /// <returns></returns>
    public List<Product> SearchProducts(int from, int max, string sorting, List<Keyword> filter, out int totalitems) {
        try {

            var predicate = PredicateBuilder.True<Product>();
            KeywordGroup previousKeywordGroup = null;
            foreach (Keyword k in filter.OrderBy(g=>g.KeywordGroup.SortOrder)) {
                if (previousKeywordGroup != k.KeywordGroup) {
                    previousKeywordGroup = k.KeywordGroup;

                    predicate = predicate.And(p => p.Keywords.Contains(k));
                }
                else
                    predicate = predicate.Or(p => p.Keywords.Contains(k));
            }

            var products = context.Products.AsExpandable().Where(predicate);

            //var products = from p in context.Products
            //               from k in p.Keywords
            //               where filter.Contains(k)
            //               select p;

            totalitems = products.Distinct().Count();
            if (sorting == "asc")
                return products.Where(x => x.Visible == true).Distinct().Skip(from).Take(max).OrderBy(o => o.SellingPrice).ToList();
            else
                return products.Where(x => x.Visible == true).Distinct().Skip(from).Take(max).OrderByDescending(o => o.SellingPrice).ToList();
        }
        catch (Exception ex) {
            throw ex;
        }
    }

================================

It doesn't work, though.

Can you help me out?

Thanks!
Daniel

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

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

发布评论

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

评论(2

单调的奢华 2024-11-05 13:53:07

您需要在循环中为每个关键字使用临时变量。从 谓词生成器页面

循环中的临时变量是
需要避免外部变量
陷阱,其中相同的变量是
为每次迭代捕获
foreach 循环。

请尝试这样做:

foreach (Keyword k in filter.OrderBy(g=>g.KeywordGroup.SortOrder)) {
    Keyword temp = k;
    if (previousKeywordGroup != k.KeywordGroup) {
        previousKeywordGroup = k.KeywordGroup;

        predicate = predicate.And(p => p.Keywords.Contains(temp));
    }
    else
        predicate = predicate.Or(p => p.Keywords.Contains(temp));
}

请注意在使用谓词 AndOr 的每一行中使用 temp

You need to use a temporary variable in the loop for each keyword. From the Predicate Builder page:

The temporary variable in the loop is
required to avoid the outer variable
trap, where the same variable is
captured for each iteration of the
foreach loop.

Try this instead:

foreach (Keyword k in filter.OrderBy(g=>g.KeywordGroup.SortOrder)) {
    Keyword temp = k;
    if (previousKeywordGroup != k.KeywordGroup) {
        previousKeywordGroup = k.KeywordGroup;

        predicate = predicate.And(p => p.Keywords.Contains(temp));
    }
    else
        predicate = predicate.Or(p => p.Keywords.Contains(temp));
}

Notice the use of temp in each line where predicate And and Or are used.

甜味超标? 2024-11-05 13:53:07

这只是制作一个很大的 AndOr 语句列表,您需要将它们分组在一起。

像这样的东西..

        var grouped = filter.GroupBy(item => item.KeyWordGroup, item => item.KeyWords);

        foreach (var item in grouped)
        {
            var innerPredicate = PredicateBuilder.True<Product>();
            foreach (var inner in item)
            {
                innerPredicate = innerPredicate.Or(p => item.Contains(k));  
            }
            predicate = predicate.And(innerPredicate);  //not sure this is correct as dont have IDE..
        }

This is just making a big list of And ands Or statements, you need to group them together.

Something like this..

        var grouped = filter.GroupBy(item => item.KeyWordGroup, item => item.KeyWords);

        foreach (var item in grouped)
        {
            var innerPredicate = PredicateBuilder.True<Product>();
            foreach (var inner in item)
            {
                innerPredicate = innerPredicate.Or(p => item.Contains(k));  
            }
            predicate = predicate.And(innerPredicate);  //not sure this is correct as dont have IDE..
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文