C# C Lambda/扩展方法在4个实体之间展平结果?

C# C Lambda/扩展方法在4个实体之间展平结果?,c#,entity-framework,lambda,C#,Entity Framework,Lambda,我在EF6中有一个标记实体,它与其他3个实体具有一对多关系: Tag / | \ Definition Variant Machine Tag { Id : 1, Name : New York, Definition { Id : 1, Title: EquipA }, Definition { Id : 2,

我在EF6中有一个标记实体,它与其他3个实体具有一对多关系:

              Tag
          /    |      \
Definition   Variant   Machine  

Tag
{
    Id : 1,
    Name : New York,
    Definition
    {
        Id : 1,
        Title: EquipA
    },
    Definition
    {
        Id : 2,
        Title: EquipB
    },
    Variant
    {
        Id : 1,
        Name: EquipA11
    },
    Variant
    {
        Id : 2,
        Name: EquipB11
    },
    Machine
    {
        Id : 1,
        Plant : New York,
        Line : 1A
    }
    Machine
    {
        Id : 2,
        Plant : New York,
        Line : 2B
    }
}
var temp = db.Tags.Include(c => c.Definition)
              .Include(v => v.Variant)
              .Include(p => p.PaperMachine)
              .SelectMany(t => t.Definition)
              .Select(t => new { t.Id, t.Title } )
              //.SelectMany(c => c.Definition, v => v.Variant,  )
              //.SelectMany(v => v.)
              .ToList();
我想返回所有4个实体的展平结果,因此得到如下结果:

Tag.Id, Tag.Name, Tag.Definition.Id, Tag.Definition.Title, Tag.Variant.Id, Tag.Variant.Name, Tag.Machine.Id, Tag.Machine.Plant, Tag.Machine.Line

1, New York, 1, EquipA, 1, EquipA11, 1, New York, 1A
1, New York, 1, EquipA, 1, EquipA11, 2, New York, 2B
1, New York, 1, EquipA, 2, EquipB11, 1, New York, 1A
1, New York, 1, EquipA, 2, EquipB11, 2, New York, 2B
1, New York, 2, EquipB, 1, EquipA11, 1, New York, 1A
1, New York, 2, EquipB, 1, EquipA11, 2, New York, 2B
1, New York, 2, EquipB, 2, EquipB11, 1, New York, 1A
1, New York, 2, EquipB, 2, EquipB11, 2, New York, 2B  
我能够做到这一点,但我只能得到定义,不知道如何从所有4个实体中进行选择:

              Tag
          /    |      \
Definition   Variant   Machine  

Tag
{
    Id : 1,
    Name : New York,
    Definition
    {
        Id : 1,
        Title: EquipA
    },
    Definition
    {
        Id : 2,
        Title: EquipB
    },
    Variant
    {
        Id : 1,
        Name: EquipA11
    },
    Variant
    {
        Id : 2,
        Name: EquipB11
    },
    Machine
    {
        Id : 1,
        Plant : New York,
        Line : 1A
    }
    Machine
    {
        Id : 2,
        Plant : New York,
        Line : 2B
    }
}
var temp = db.Tags.Include(c => c.Definition)
              .Include(v => v.Variant)
              .Include(p => p.PaperMachine)
              .SelectMany(t => t.Definition)
              .Select(t => new { t.Id, t.Title } )
              //.SelectMany(c => c.Definition, v => v.Variant,  )
              //.SelectMany(v => v.)
              .ToList();

听起来像是要在所有相关实体之间生成笛卡尔坐标系

像这样的事情应该会得到你想要的结果:

var temp = db.Tags
    .SelectMany(t => t.Definitions
        .SelectMany(d => d.Tag.Variants
            .SelectMany(v => v.Tag.PaperMachines
                .Select(p => new 
                {
                   TagId = t.Id, 
                   TagName = t.Name,
                   DefinitionId = d.Id,
                   DefinitionName = d.Name,
                   VariantId = v.Id,
                   VariantName = v.Name,
                   PaperMachineId = p.Id,
                   PaperMachineName = p.Name
                })))).ToList();
这将使用请求的详细信息填充匿名类型。如果需要返回调用方/视图,可以定义DTO/ViewModel来填充和返回。这需要双向导航属性从标记获取到每个子级并返回到标记。或者你也可以使用Join,不过我觉得读起来会有点混乱

也许有一种更简洁的方法可以得到它。通常情况下,我是在帮助人们避开卡特尔人,而不是故意制造他们

编辑:对于多对多关系,您可以使用上述查询,而无需反向导航属性

var temp = db.Tags
    .SelectMany(t => t.Definitions
        .SelectMany(d => t.Variants
            .SelectMany(v => t.PaperMachines
                .Select(p => new 
                {
                   TagId = t.Id, 
                   TagName = t.Name,
                   DefinitionId = d.Id,
                   DefinitionName = d.Name,
                   VariantId = v.Id,
                   VariantName = v.Name,
                   PaperMachineId = p.Id,
                   PaperMachineName = p.Name
                })))).ToList();
这看起来有点奇怪,但似乎确实起到了作用。请注意,对于SelectMany联接,我们在t上重新联接。引用,但这仍然允许我们在最终选择中加入标记、定义、变体和纸机引用的组合


请谨慎,因为随着您引入更多的组合,这将变得指数级更大、更昂贵。

Intellisense不允许我这样做:var temp=db.Tags.SelectManyt=>t.Definitions.SelectManyd=>d.Tags.Variants-它只允许我这样做:var temp=db.Tags.SelectManyt=>t.Definitions.SelectManyd=>d、 Tag.FirstOrDefault.Variants-我认为多个selectMany只用于嵌套实体,而不是同级实体否,它可以跨同级使用。您的错误可能是由于标记和变量之间存在多对多关系。我的例子是假设一对多。标记有变量,变量返回到标记我将添加一个编辑到解决方案中,因为它仍然可以处理多对多。。。