2012-07-16 84 views
3

我有查詢:的LINQ取不同

ID ItemID RecommendItemID Message 
------------------------------------------ 
1  25  3     Msg here 
2  26  3     Something else 
3  27  8     Another message 

我需要查詢,以篩選出具有相同RecommendItemID,這應該結果:

var q = (
    from c in db.tblStoreRecommendations 
    where 
    itemIDsInCart.Contains(c.ItemID) 
    && !itemIDsInCart.Contains(c.RecommendItemID) 
    select c 
); 

它將沿着線返回的東西不會多次出現在返回的結果中。

如果存在兩個,它可以使用(隨機選擇將是最好的)。所以返回的結果應該省略記錄ID 1或2.

任何人都可以告訴我如何做到這一點嗎?謝謝!

回答

6

一種方法是使用的GroupBy,然後從每組中選擇第一項:

var q = (
    from c in db.tblStoreRecommendations 
    where 
     itemIDsInCart.Contains(c.ItemID) 
    && !itemIDsInCart.Contains(c.RecommendItemID) 
    select c 
).GroupBy(c => c.RecommendItemID) 
.Select(g => g.First()); 

如果您使用此顯示隨機審查,我會建議強加於到這使用代碼而不是LINQ查詢,通過省略First像這樣:

var q = (
    from c in db.tblStoreRecommendations 
    where 
     itemIDsInCart.Contains(c.ItemID) 
    && !itemIDsInCart.Contains(c.RecommendItemID) 
    select c 
).GroupBy(c => c.RecommendItemID) 
.Select(g => g.ToArray()); 

var random = new Random(); 
foreach (var r in q) 
{ 
    var rec = r[random.Next(r.Length)]; 
    // use your recommendation 
} 
+0

非常感謝!但是有一個問題,它不會隨機重複。任何想法在這一個? – 2012-07-16 20:40:13

+0

@TomGullen我[給了它一個嘗試](http://stackoverflow.com/a/11512299/1106367)... – Adam 2012-07-16 20:52:09

+0

@TomGullen:我已經提供了另一種方式(少隨機選擇LINQ)。 – user7116 2012-07-16 20:58:57

3

我相信你可以添加一個明顯的對比您的LINQ表達式的末尾,就像:

var q = (
    from c in db.tblStoreRecommendations 
    where 
    itemIDsInCart.Contains(c.ItemID) 
    && !itemIDsInCart.Contains(c.RecommendItemID) 
    select c 
) 
.Distinct((x, y) => x.RecommendItemID == y.RecommendItemID); 

編輯

我才意識到我該使用擴展的方法,我寫我自己,通常保持方便的做...這裏是它的代碼:

/// <summary> 
    /// Provides a way to get a distinct list of items based on a lambda comparison operator. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="source"></param> 
    /// <param name="equalityComparer">A comparison function that returns true of the two items are considered equal.</param> 
    /// <returns>The list of distinct items.</returns> 
    public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> equalityComparer) 
    { 
     var distincts = new List<T>(); 
     foreach (var item in source) 
     { 
      var found = false; 
      foreach (var d in distincts) 
      { 
       found = equalityComparer(item, d); 
       if (found) 
        break; 
      } 

      if (!found) 
      { 
       distincts.Add(item); 
       yield return item; 
      } 
     } 
    } 
+1

請注意,您需要創建一個實現'IEqualityComparer '的類,而不是直接使用lambda。見http://msdn.microsoft.com/en-us/library/bb338049.aspx – 2012-07-16 20:32:45

+1

相信鮮明的重載採用一個類型實現'的IEqualityComparer ',而不是一個謂語。 – user7116 2012-07-16 20:34:17

+0

嗯,你是對的,我在一個現有的項目中輸入VisualStudio,我只是碰巧有我自己的擴展方法來完成它...查看我的編輯。 – CodingWithSpike 2012-07-16 20:37:25

1

讓我們儘可能使用查詢表達式來堅持這一點:

var q = from c in db.tblStoreRecommendations 
     where itemIDsInCart.Contains(c.ItemID) 
      && !itemIDsInCart.Contains(c.RecommendItemID) 
     group c by c.RecommendItemID into matches 
     select matches.First(); 

上下文關鍵字into當然在這裏派上用場。

這裏是如何randomize它:

private static Random random = new Random(); 

var q = from c in db.tblStoreRecommendations 
     where itemIDsInCart.Contains(c.ItemID) 
      && !itemIDsInCart.Contains(c.RecommendItemID) 
     group c by c.RecommendItemID 
     into matches 
     select matches.AsEnumerable().ElementAt(random.Next(matches.Count())); 

由於LINQ到SQL無法處理ElementAt電話,我選擇前編輯答案執行查詢(通過調用AsEnumerable)分組中的Random元素。

+0

+1,但我不確定L2S或L2E如何處理ElementAt/Count組合。您可能需要在兩者之間進行AsEnumerable調用以實現結果。 – user7116 2012-07-16 21:01:15

+0

好點,我家裏沒有SQL服務器......有人可以證實這一點嗎? – Adam 2012-07-16 21:02:27

+0

謝謝,但我得到的錯誤'System.NotSupportedException:查詢經營者的ElementAt'不supported.' – 2012-07-16 21:04:35