我对PredicateBuilder有一个疑问,我真的希望你能就如何解决这个问题给我一些建议。我会试着解释一下。
我认为人们可以根据关键字搜索产品。每个关键字都属于一个关键字组,因此一些真实数据将是:
KeywordGroup / Keyword
类型 - 链/
类型 - 手镯/
颜色 - 紫色/
颜色 - 绿色
现在我希望得到以下结果:
在每个不同的KeywordGroup之间应该有一个OR。 在KeywordGroup内的每个不同的关键字之间应该有一个AND。
例如,用户希望只搜索颜色为Purlple或Green的手镯。
这个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;
}
}
================================
但是,它不起作用。 你可以帮帮我吗?谢谢! 丹尼尔
答案 0 :(得分:3)
您需要在循环中为每个关键字使用临时变量。来自Predicate Builder page:
循环中的临时变量是 要求避免外部变量 陷阱,其中相同的变量是 为每次迭代捕获 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));
}
请注意,在使用谓词temp
和And
的每一行中使用Or
。
答案 1 :(得分:0)
这只是制作And
和Or
语句的大列表,您需要将它们组合在一起。
像这样......
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..
}