LINQ(lambda语法)为多对多关系选择

LINQ(lambda语法)为多对多关系选择,linq,select,lambda,many-to-many,Linq,Select,Lambda,Many To Many,我拥有与关系相关的实体: 包装M--N工厂 M--N元件的封装 f、 e.表格内容为:包装(类型1)有工厂(A、B、C)和组件(1、2、3、4) 我想写LINQ,它将给我以下结果: 类型1 A 1 类型1和类型2 类型1 A 3 类型1和类型4 类型1 B 1 类型1 B 2 类型1 B 3 类型1 B 4 类型1 C 1 类型1 C 2 类型1 C 3 类型1 C 4 如何使用LINQ和lambda语法来实现这一点?您要寻找的是笛卡尔积。我将定义两个小对象,以便显示一个具体的LINQ查询。为了

我拥有与关系相关的实体:

包装M--N工厂
M--N元件的封装

f、 e.表格内容为:包装(类型1)有工厂(A、B、C)和组件(1、2、3、4)

我想写LINQ,它将给我以下结果:

类型1 A 1
类型1和类型2
类型1 A 3
类型1和类型4
类型1 B 1
类型1 B 2
类型1 B 3
类型1 B 4
类型1 C 1
类型1 C 2
类型1 C 3
类型1 C 4


如何使用LINQ和lambda语法来实现这一点?

您要寻找的是笛卡尔积。我将定义两个小对象,以便显示一个具体的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}
                        };
这将导致输出:

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的答案。

您希望从每个源项中选择多个对象因此使用
选择多个
操作符

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
        })

这看起来也很棒,但我使用了nlips的代码。Thanks@Peter如果回答有趣,请投票!阅读如何将此选择修改为外部联接?因为当包装没有任何组件或工厂时,我不会得到这种包装。我想退回所有的包装,无论有没有组件或工厂
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
        })