我正在使用C#3.5我有IList<MyItemLinkProperty>
,其中MyItemLinkProperty
表示项目与其属性(一个或多个)之间的链接。它有ItemId
,PropertyId
,PropertyValue
。在此列表中,ItemId
可以多次出现,因为项目可以具有许多属性,颜色,大小等。(这是与性能相关的问题,我有这种列表并且没有映射到项目实体)。
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的项目。例如'red'和'small'。这应该给我ItemID
1001具有这两个属性。
在伪代码中我想我是在“给我属性id为1或2且项目ID相同的项目”。然后我知道有一些具有这两种属性的物品。
我在想一个linq查询会这样做。但是没有得到这个工作并陷入困境。也许我在这里阻止了我的思绪,过度思考并使其过于复杂......
为此提供最佳解决方案的任何提示?
答案 0 :(得分: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 :(得分:2)
我遇到过类似的问题并使用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的性能也非常好(没有像使用Any
或All
时那样的子查询)
答案 2 :(得分:1)
您可以定义所需的属性列表,例如:
var desiredProperties = new[]{ "Red", "Small" };
然后您可以使用Enumerable.All
和Contains
:
var allMatchingItemProperties = allItemProperties
.Where(ip => desiredProperties.All(dp => ip.Properties.Contains(dp)));