2011-04-01 55 views
2

我有一個關於PredicateBuilder的問題,我真的希望你能給我一些關於如何解決這個問題的建議。我會盡力解釋這一點。PredicateBuilder多個AND問題

我有這種情況,人們可以根據關鍵字搜索產品。每個關鍵字屬於keywordgroup,所以一些真實的數據是:

KeywordGroup /關鍵字

類型 - 鏈/

類型 - 手鍊/

顏色 - 紫色/

顏色 - 綠色

現在我想要得到以下結果:

在每個不同的KeywordGroup之間應該有一個OR。 在關鍵字組內的每個不同關鍵字之間應該有一個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; 
     } 
    } 

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

它不工作,雖然。

你能幫我嗎?

謝謝! Daniel

回答

0

這只是製作一個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.. 
     } 
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其中使用謂詞AndOr