簡體   English   中英

Linq查詢中的父子關系

[英]Parent child relation in Linq query

在實體類中

我在實體類中有兩個父表“ TestParent”和“ TestTag”,而在實體類中沒有更新的子表“ TestChild”之一。 所以我可以加入TestParent和TestChild表(兩者都是foreinkey主要關系)。

問題:我無法在Linq查詢中選擇子表TestChild

表:TestTag:

在此處輸入圖片說明

表:TestParent:

在此處輸入圖片說明

孩童:TestChild

在此處輸入圖片說明

在下面的實體類中

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

因此,您具有三個表: TestTags表, TestParents表和帶有TestChildren的表。

每個TestTag都有零個或多個TestChildren 每個TestChild使用外鍵完全屬於一個TestTag 直接的一對多關系

每個TestParent還具有零個或多個TestChildren 每個TestChild都有一個使用外鍵的TestParent

如果您遵循實體框架代碼優先約定 ,那么您將擁有類似於

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

在實體框架中,表的列由非虛擬屬性表示。 虛擬屬性表示表之間的關系(一對多,多對多,...)

這樣,TestTag 4和TestParent 5可以有兩個子代。 如果您不想要,請考慮創建組合的主鍵[TestTagId,TestParentId]

如果TestChild除了外鍵之外沒有其他屬性,那么實際上您將在TestTag和TestParent之間創建多對多關系。 在這種情況下,您不必提及TestChild表。

為了完整起見,DbContext:

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

這是實體框架檢測您的關系以及主鍵和外鍵所需要知道的全部內容。 因為我遵循了約定的屬性,所以也不需要流利的API,除非是因為非標准的復數形式Children

所以我可以加入TestParent和TestChild表

好了,您可以執行(group-)join,但是使用ICollections通常更容易

給我...的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(),
    });

有些人喜歡改用GroupJoin。 如果您希望這樣做,並且可以說服項目負責人與使用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(),
    });

恕我直言:這看起來太可怕了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM