简体   繁体   English

Linq查询中的父子关系

[英]Parent child relation in Linq query

In the Entity Class 在实体类中

I have two parent table "TestParent" and "TestTag" in Entity class and one of the child table "TestChild" which is not updated in Entity class. 我在实体类中有两个父表“ TestParent”和“ TestTag”,而在实体类中没有更新的子表“ TestChild”之一。 so can I Join the TestParent and TestChild table (both are foreinkey primary relation). 所以我可以加入TestParent和TestChild表(两者都是foreinkey主要关系)。

Issue: I am not able to select child table TestChild in Linq query 问题:我无法在Linq查询中选择子表TestChild

Table : TestTag: 表:TestTag:

在此处输入图片说明

Table: TestParent: 表:TestParent:

在此处输入图片说明

Childtable: TestChild 孩童:TestChild

在此处输入图片说明

In Entity class below 在下面的实体类中

public DbSet<TestParent> Questions { get; set; }
  public DbSet<TestTag> Tags { get; set; }

So you have three tables: a table of TestTags , a table of TestParents and a table with TestChildren . 因此,您具有三个表: TestTags表, TestParents表和带有TestChildren的表。

Every TestTag has zero or more TestChildren ; 每个TestTag都有零个或多个TestChildren every TestChild belongs to exactly one TestTag , using a foreign key. 每个TestChild使用外键完全属于一个TestTag A straightforware one-to-many relation 直接的一对多关系

Every TestParent also has zero or more TestChildren ; 每个TestParent还具有零个或多个TestChildren every TestChild has exactly one TestParent , using a foreign key. 每个TestChild都有一个使用外键的TestParent

If you followed the entity framework code first conventions , you would have something similar to 如果您遵循实体框架代码优先约定 ,那么您将拥有类似于

class TestTag
{
    public int Id {get; set;}
    ...  // other properties

    // every TestTag has zero or more TestChildren (one-to-many)
    public virtual ICollection<TestChild> TestChildren {get; set;}
}
class TestParent
{
    public int Id {get; set;}
    ...  // other properties

    // every TestParent has zero or more TestChildren (one-to-many)
    public virtual ICollection<TestChild> TestChildren {get; set;}
}
class TestChild
{
    public int Id {get; set;}
    ...  // other properties

    // every TestChild has exactly one TestParent using foreign key
    public int TestParentId {get; set;}
    public virtual TestParent TestParent {get; set;}

    // every TestChild has exactly one TestTag using foreign key
    public int TestTagId {get; set;}
    public virtual TestTag TestTag {get; set;}
}

In entity framework the columns of the tables are represented by non-virtual properties. 在实体框架中,表的列由非虚拟属性表示。 The virtual properties represent the relations between the tables (one-to-many, many-to-many, ...) 虚拟属性表示表之间的关系(一对多,多对多,...)

This way it is possible for TestTag 4 and TestParent 5 to have two Children. 这样,TestTag 4和TestParent 5可以有两个子代。 If you don't want, consider creating a combined primary key [TestTagId, TestParentId] 如果您不想要,请考虑创建组合的主键[TestTagId,TestParentId]

If TestChild has no other properties than the foreign keys, than in fact you are creating a many-to-many relation between TestTag and TestParent. 如果TestChild除了外键之外没有其他属性,那么实际上您将在TestTag和TestParent之间创建多对多关系。 In that case you don't have to mention the TestChild table. 在这种情况下,您不必提及TestChild表。

For completeness the DbContext: 为了完整起见,DbContext:

class MyDbContext : DbContext
{
     public DbSet<TestTag> TestTags {get; set;}
     public DbSet<TestParent> TestParents {get; set;}
     public DbSet<TestChild> TestChildren {get; set;}
}

This is all that entity framework needs to know to detect your relations and the primary and foreign keys. 这是实体框架检测您的关系以及主键和外键所需要知道的全部内容。 Because I followed the conventions attributes nor fluent API is necessary, except maybe because of the non-standard plural form Children . 因为我遵循了约定的属性,所以也不需要流利的API,除非是因为非标准的复数形式Children

so can I Join the TestParent and TestChild table 所以我可以加入TestParent和TestChild表

Well you can do a (group-)join, but it is usually easier to use the ICollections 好了,您可以执行(group-)join,但是使用ICollections通常更容易

Give me the TestParents that ... with all their TestChildren and TestTags that ... 给我...的TestParents及其所有的TestChildren和TestTags ...

var result = dbContext.TestParents
    .Where(parent => ...)             // if you don't want all testParents
    .Select(parent => new
    {
        // select only the properties you plan to use
        Id = parent.Id,
        Name = parent.Name,

        Children = parent.TestChildren
            .Where(child => child.TestTag.Name = "My Test Tag Name")
            .Select(child => new
            {
                Name = child.TestTag.Name,
                ...
            })
            .ToList(),
    });

Some people prefer to do a GroupJoin instead. 有些人喜欢改用GroupJoin。 If you want that, and you can convince your project leader that a GroupJoin is better readable / testable / maintainable than using the ICollections, you can do the following: 如果您希望这样做,并且可以说服项目负责人与使用ICollections相比,GroupJoin具有更好的可读性/可测试性/可维护性,则可以执行以下操作:

var result = dbContext.TestParents.GroupJoin(dbContext.TestChildren,
    parent => parent.Id,                // from each parent take the Id
    child => child.ParentId,            // from each child take the ParentId

    // resultSelector:
    (parent, children) => new
    {
        // Parent Properties:
        Id = parent.Id,
        ...

        // GroupJoin the collection of child properties with the TestTags:
        children.GroupJoin(dbContext.TestTags,
        child => child.TestTagId,          // from each TestChild take the TestTagId
        tag => tag.Id,                     // from each TestTag take the Id
        (child, tagsOfThisChild) => new
        {
            // desired Child properties
            ...

            TestTags = tagsOfThisChild.Select(tag => new
            {
                 Id = tag.Id,
                 ...
            })
            .ToList(),
        })
        .ToList(),
    });

IMHO: this looks horrible! 恕我直言:这看起来太可怕了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM