我有关系的实体:
包装M—N工厂
M—N组件
初版表的内容是:包装(类型1)有工厂(A, B, C)和组件(1,2,3,4)
我想写LINQ,它会给我的结果为:
Type1 A 1
Type1 a2
类型1 A 3
类型1 A 4
类型1 b1
类型1 b2
类型1 b3
Type1 b4
1型c1
类型1 C 2
类型1 C 3
类型1 C 4
如何使用带有lambda语法的LINQ获得此值?
您希望从每个源项中选择多个对象。所以使用SelectMany
运算符
packagingCollection.SelectMany(p => p.Components.Select(c => new {
P = p,
C = c
})).SelectMany(x => x.P.Factories.Select(f => new {
P = x.P,
C = x.C,
F = f
})).Select(y => new {
PackagingName = y.P.Name,
ComponentName = y.C.Name,
FactoryName = y.F.Name
})
你要找的是笛卡尔积。我将定义两个小对象,以便我可以显示一个具体的LINQ查询。为方便起见,我将包类型设置为enum
,但实际上,只要表示工厂和组件的对象具有相同类型的公共字段,这就无关紧要了。
private enum PackagingType
{
Type1
};
private class Factory
{
public string Name { get; set; }
public PackagingType Type { get; set; }
}
private class Component
{
public string Name { get; set; }
public PackagingType Type { get; set; }
}
var factories = new List<Factory>
{
new Factory {Name = "A", Type = PackagingType.Type1},
new Factory {Name = "B", Type = PackagingType.Type1},
new Factory {Name = "C", Type = PackagingType.Type1}
};
var components = new List<Component>
{
new Component {Name = "1", Type = PackagingType.Type1},
new Component {Name = "2", Type = PackagingType.Type1},
new Component {Name = "3", Type = PackagingType.Type1},
new Component {Name = "4", Type = PackagingType.Type1}
};
然后我们可以使用LINQ扩展方法Join
在Type
字段上连接factories
和components
,该方法为我们返回一个笛卡尔积。它看起来像:
var cartesianProduct = factories.Join(components,
factory => factory.Type,
component => component.Type,
(factory, component) =>
new
{
Type = factory.Type,
FactoryName = factory.Name,
ComponentName = component.Name
});
这会导致输出:
Type1 A 1
Type1 A 2
Type1 A 3
Type1 A 4
Type1 B 1
Type1 B 2
Type1 B 3
Type1 B 4
Type1 C 1
Type1 C 2
Type1 C 3
Type1 C 4
如果你有一个基于打包的多对多关系的第三个对象,那么你可以简单地将该对象列表与其Type
字段上的当前笛卡尔积连接起来,以获得所有三个对象的笛卡尔积。更多信息请看Eric Lippert的回答