2017-09-12 138 views
5

我已經搜索了一個合適的解決方案,使用EF Core 2.0,Code first和Fluent API來生成多對多關係。流利的API,多對多的實體框架核心2.0

一個簡單的場景是:

public class Person 
{ 
    public Person() { 
     Clubs = new HashSet<Club>(); 
    } 
    public int PersonId { get; set; } 
    public virtual ICollection<Club> Clubs { get; set; } 
} 

public class Club 
{ 
    public Club() { 
     Persons = new HashSet<Person>(); 
    } 
    public int ClubId { get; set; } 
    public virtual ICollection<Person> Persons { get; set; } 
} 

請糾正我,如果我錯了,但我可以誠實地找不到包含有關如何做到這一點使用所描述的工具精心解釋的問題。 任何人都可以解釋這是如何完成的?

回答

6

如果不使用顯式類進行連接,這在EF Core中還不可行。有關如何執行此操作的示例,請參閱here

Github上有一個開放的issue要求能夠做到這一點,而不需要明確的類,但它尚未完成。

使用您的情況,我聯繫的例子會推薦以下實體類:

public class Person 
{ 
    public int PersonId { get; set; } 
    public virtual ICollection<PersonClub> PersonClubs { get; set; } 
} 

public class Club 
{ 
    public int ClubId { get; set; } 
    public virtual ICollection<PersonClub> PersonClubs { get; set; } 
} 

public class PersonClub 
{ 
    public int PersonId { get; set; } 
    public Person Person { get; set; } 
    public int ClubId { get; set; } 
    public Club Club { get; set; } 
} 

以下OnModelCreating將被用於設置:

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<PersonClub>() 
     .HasKey(pc => new { pc.PersonId, pc.ClubId }); 

    modelBuilder.Entity<PersonClub>() 
     .HasOne(pc => pc.Person) 
     .WithMany(p => p.PersonClubs) 
     .HasForeignKey(pc => pc.PersonId); 

    modelBuilder.Entity<PersonClub>() 
     .HasOne(pc => pc.Club) 
     .WithMany(c => c.PersonClubs) 
     .HasForeignKey(pc => pc.ClubId); 
} 

一定要去開如果你覺得有需要,我會聯繫並表達你的挫折感。

編輯:開放問題建議使用簡單的Select瀏覽這個有點麻煩的層次結構。爲了從PersonId獲得Club的集合,您可以使用SelectMany。例如: -

var clubs = dbContext.People 
    .Where(p => p.PersonId == id) 
    .SelectMany(p => p.PersonClubs); 
    .Select(pc => pc.Club); 

我不能保證這是否是一個真正的「最佳實踐」,但它肯定應該做的伎倆,我認爲它公平地說,這不是過於難看。

+0

所以那就像1-Many-Many-1?我有點難過,他們不支持這個功能,但謝謝你的答案。 – Anonymous

+0

看起來你並不孤單與你的悲傷。儘管對EF英孚團隊公平 - 對他們來說有很多事情要做。 –

+0

能給我檢索根據PERSONID一個俱樂部,通過加入類最佳實踐LINQ的解決方案? – Anonymous

1

因此,每Person有零個或多個Clubs和每個Club有零個或多個Persons。正如你所說的,這是一個適當的多對多關係。

您可能知道關係數據庫需要額外的表來實現這種多對多關係。關於實體框架的好處是它能夠識別這種關係併爲你創建這個額外的表格。

乍一看這似乎是一個問題,這額外的表是不是在你的DbContext一個dbSet:「如何執行這個額外的表聯接,如果我不是有這方面的DbSet怎麼辦?」。

幸運的是,您不需要在查詢中提及這個額外的表。

如果您需要像「給我所有'俱樂部'這樣的查詢......來自每個'...'的人......」不要聯合考慮。而是使用ICollections!

獲取所有的「李四」的人與他們參加所有國家的俱樂部:

var result = myDbContext.Persons 
    .Where(person => person.Name == "John Doe") 
    .Select(person => new 
    { 
     PersonId = person.Id, 
     PersonName = person.Name, 
     AttendedCountryClubs = person.Clubs 
      .Where(club => club.Type = ClubType.CountryClub), 
    }; 

實體框架將認識到,與加入額外的多對許多需要表,將執行此連接,沒有你提到這張額外的桌子。

反過來:獲取所有鄉村俱樂部與他們的「李四」的人:

var result = myDbContext.Clubs 
    .Where(club => club.Type = ClubType.CountryClub) 
    .Select(club => new 
    { 
     ClubId = club.Id, 
     ClubName = club.Name, 
     AnonymousMembers = club.Persons 
      .Where(person => person.Name == "John Doe"), 
    } 

我所經歷的,一旦我開始想,我想,而不是加入我的收藏產生需要獲得這些集合我發現我幾乎不使用連接。這是一個一對多的關係以及許多一對多關係的情況。實體框架將在內部使用適當的連接。

4

正確的 「設置」 用於此是:

public class Person 
{ 
    public int PersonId { get; set; } 
    public virtual ICollection<PersonClub> PersonClubs { get; set; } 
} 

public class Club 
{ 
    public int ClubId { get; set; } 
    public virtual ICollection<PersonClub> PersonClubs { get; set; } 
} 

public class PersonClub 
{ 
    public int PersonId { get; set; } 
    public Person Person { get; set; } 
    public int ClubId { get; set; } 
    public Club Club { get; set; } 
} 
protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<PersonClub>() 
     .HasKey(pc => new { pc.PersonId, pc.ClubId }); 
} 

所以,此塊用於配置 「膠表」 是必要如@Kirk例如:

modelBuilder.Entity<PersonClub>() 
    .HasOne(pc => pc.Person) 
    .WithMany(p => p.PersonClubs) 
    .HasForeignKey(pc => pc.PersonId); 

modelBuilder.Entity<PersonClub>() 
    .HasOne(pc => pc.Club) 
    .WithMany(c => c.PersonClubs) 
    .HasForeignKey(pc => pc.ClubId); 
+0

如果使用鏈接實體中的[ForeignKey]屬性不需要任何代碼。即使如此:可悲的是,這不像早期版本。民國4年開發的核心,他們一直沒能做出符合以前的版本。 –