2013-01-31 43 views
4

我使用C#3.5我有一個IList<MyItemLinkProperty>,其中MyItemLinkProperty表示項目之間的聯繫,它的屬性(一個或多個)。它有ItemId,PropertyId,PropertyValue。在這個列表ItemId可以發生多次,因爲一個項目可以有很多屬性,顏色,大小等(這是一個性能相關的問題,我有這種列表,並沒有映射到一個項目實體)。C#LINQ選擇項目棘手的過濾

    ItemID PropId PropValue 
itemProperty1 = { 1001, 1,  'Red' } 
itemProperty2 = { 1001, 2,  'Small' } 
itemProperty3 = { 1002, 1,  'Red' } 
itemProperty4 = { 1002, 3,  'Medium' } 
itemProperty5 = { 1003, 4,  'Green' } 
itemProperty6 = { 1003, 2,  'Small' } 

現在我需要找到所有具有屬性A和屬性B的項目。例如「紅色」和「小」。這應該給我ItemID 1001具有這兩個屬性。

在僞代碼,我想以後「給我的項目,其中物業編號爲1或2,項目ID是一樣的」我是。然後我知道有一個物品具有這兩個屬性。

我想LINQ查詢將做到這一點。但沒有得到這個工作,並陷入困境。也許我在這裏擋住了我的心,思前想它並使它過於複雜...

爲這個最好的解決方案有什麼建議?

+0

你有什麼試過?如果你沒有努力解決問題,人們不會幫助你...... –

+0

「如果你沒有努力解決問題,人們不會幫助你。」它不是永遠是真的) – MikroDel

+0

我覺得我反正走錯了衚衕,想要「沒有污點」的想法,所以我試着問一個問題,如果有人有一些提示。很高興有人有! – Martin

回答

5

你需要按ItemID,然後檢查每組包含的所有值,像這樣:

var smallRedIds = allItems 
    .GroupBy(i => i.ItemID) 
    .Where(g => g.Any(x => x.PropId == 1 && x.PropValue == "Red") 
      && g.Any(x => x.PropId == 2 && x.PropValue == "Small")) 
    .Select(g => g.Key); 

這將產生有兩個「小」和「紅」屬性的所有項目id的枚舉。

+1

像魅力一樣工作,謝謝!現在我通過分組和條件學到了一些新的東西。通過這樣的工作,我能夠通過這麼多愚蠢的手段提高性能。 – Martin

1

你可以定義你需要perperties的列表,如:

var desiredProperties = new[]{ "Red", "Small" }; 

然後你可以使用Enumerable.AllContains

var allMatchingItemProperties = allItemProperties 
    .Where(ip => desiredProperties.All(dp => ip.Properties.Contains(dp))); 
+0

看起來很乾淨,我喜歡。不過,我需要匹配上面的多個標準,不確定此解決方案在這種情況下工作。但是,無論如何,這是一個乾淨的解決方案,我會記住將來的過濾問題。 – Martin

1

我也碰到過類似的問題,並使用JOIN解決它。它可以很容易地再用來生成動態查詢:

int[] propertyIds = new []{1,2,3,4}; 
var query = dc.ItemProperties.Where(i=> i.PropId == propertyIds[0]); 

for (int i = 1; i < catsGroups.Length;i++) 
{ 
    query = query.Join(dc.ItemProperties.Where(i=> i.PropId == propertyIds[i]), x => x.IDItem, x => x.IDItem,(x, y) => x); 
} 
return input; 

有一個好處,這將讓你的項目都希望列(不像GROUP BY),這可能是在某些情況下有益的。生成的SQL的性能也非常好(當使用AnyAll時,沒有子查詢)