4

我正在使用 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 的项目。例如“红色”和“小”。这应该给我ItemID1001 具有这两个属性。

在伪代码中,我想我在“给我属性 id 为 1 或 2 且项目 id 相同的项目”。然后我知道一个拥有这两个属性的项目。

我在想一个 linq 查询会做到这一点。但是没有得到这个工作并被卡住了。也许我在这里阻塞了我的思想,过度思考并让它变得过于复杂......

对此有最佳解决方案的任何提示?

4

3 回答 3

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 的枚举。

于 2013-01-31T11:28:11.903 回答
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 不同),这在某些情况下可能会有所帮助。Any生成的 SQL 的性能也非常好(使用or时没有子查询All

于 2013-01-31T13:23:16.853 回答
1

您可以定义所需的属性列表,例如:

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

然后你可以使用Enumerable.Alland Contains

var allMatchingItemProperties = allItemProperties
    .Where(ip => desiredProperties.All(dp => ip.Properties.Contains(dp)));
于 2013-01-31T11:29:43.960 回答