Fluent API,Entity Framework Core 中的多对多 [英] Fluent API, many-to-many in Entity Framework Core

查看:33
本文介绍了Fluent API,Entity Framework Core 中的多对多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在 stackoverflow 中搜索了使用 EF Core、Code first 和 Fluent API 生成多对多关系的正确解决方案.

一个简单的场景是:

公共类人{公共人(){Clubs = new HashSet();}公共 int PersonId { 获取;放;}公共虚拟 ICollection<Club>俱乐部{得到;放;}}公开课俱乐部{公共俱乐部(){Persons = new HashSet();}公共 int ClubId { 获取;放;}公共虚拟 ICollection人{得到;放;}}

如果我错了,请纠正我,但老实说,我找不到一个问题,其中包含有关如何使用所描述的工具执行此操作的详细说明.谁能解释一下这是怎么做到的?

解决方案

EF Core 5.0 RC1+

从 EF Core 5.0 RC1 开始,可以在没有显式连接表的情况下执行此操作.EF Core 能够为问题中显示的多对多关系配置映射,而无需您创建 PersonClub 类型.

参见 EF Core 5.0、RC1、Many-to-many 中的新功能,请参阅官方文档以获取更多信息.

以前的版本

如果不使用显式的连接类,这在 EF Core 中是不可能的.请参阅此处了解如何执行此操作的示例.>

Github 上有一个开放的问题,要求能够在不需要的情况下执行此操作用于显式类,但尚未完成.

使用您的方案,我链接的示例将推荐以下实体类:

公共类人{公共 int PersonId { 获取;放;}公共虚拟 ICollectionPersonClubs { 得到;放;}}公开课俱乐部{公共 int ClubId { 获取;放;}公共虚拟 ICollectionPersonClubs { 得到;放;}}公共课程 PersonClub{公共 int PersonId { 获取;放;}公共人人{得到;放;}公共 int ClubId { 获取;放;}公共俱乐部俱乐部{得到;放;}}

然后将使用以下 OnModelCreating 进行设置:

protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity().HasKey(pc => new { pc.PersonId, pc.ClubId });modelBuilder.Entity().HasOne(pc => pc.Person).WithMany(p => p.PersonClubs).HasForeignKey(pc => pc.PersonId);modelBuilder.Entity().HasOne(pc => pc.Club).WithMany(c => c.PersonClubs).HasForeignKey(pc => pc.ClubId);}

如果您觉得有必要,请务必转到我链接的未解决问题并表达您的不满.

未解决的问题建议使用简单的 Select 来浏览这个有点麻烦的层次结构.为了从 PersonIdClub 的集合,您可以使用 SelectMany.例如:

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

我不能保证这是否真的是最佳实践",但它肯定能奏效,我认为可以说它并不过分丑陋.

I've searched stackoverflow for a proper solution on generating a many-to-many relationship, using EF Core, Code first and Fluent API.

A simple scenario would be:

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

Please correct me if im wrong but I could honestly not find a question that contains an elaborate explanation on how to do this using the described tools. Can anyone explain how this is done?

解决方案

EF Core 5.0 RC1+

As of EF Core 5.0 RC1, it's possible to do this without an explicit join table. EF Core is able to configure a mapping for the many-to-many relationship shown in your question without requiring you to create a PersonClub type.

See What's New in EF Core 5.0, RC1, Many-to-many in the official docs for more information.

Previous Versions

This is not yet possible in EF Core without using an explicit class for the join. See here for an example of how to do that.

There's an open issue on Github asking for the ability to do this without the need for an explicit class, but it has not yet been completed.

Using your scenario, the example I linked would recommend the following entity classes:

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

The following OnModelCreating would then be used for setup:

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

Be sure to go to the open issue I linked and voice your frustration if you feel the need.

EDIT: The open issue suggests using a simple Select to navigate through this somewhat cumbersome hierarchy. In order to get from a PersonId to a collection of Clubs, you can use SelectMany. e.g.:

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

I can't vouch for whether this is truly a "best practice", but it should certainly do the trick and I think its fair to say it's not overly ugly.

这篇关于Fluent API,Entity Framework Core 中的多对多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆