Fluent API,Entity Framework Core 2.0中的多对多

Ano*_*ous 33 c# entity-framework code-first ef-fluent-api

我使用EF Core 2.0,Code first和Fluent API 搜索stackoverflow以获得生成多对多关系的正确解决方案.

一个简单的场景是:

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

Kir*_*kin 35

如果不使用显式类进行连接,则在EF Core中尚不可能.请参阅此处以获取如何执行此操作的示例.

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

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

如果你觉得有必要的话,一定要去找我关联的公开问题,并表达你的挫折感.

编辑:开放的问题建议使用一个简单的方法Select来浏览这个有点繁琐的层次结构.为了从一个s PersonId集合中获取Club,你可以使用SelectMany.例如:

var clubs = dbContext.People
    .Where(p => p.PersonId == id)
    .SelectMany(p => p.PersonClubs);
    .Select(pc => pc.Club);
Run Code Online (Sandbox Code Playgroud)

我不能保证这是否是一个真正的"最佳实践",但它肯定应该做的伎俩,我认为它公平地说,这不是过于难看.


pau*_*del 19

正确的"设置"是:

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 });
}
Run Code Online (Sandbox Code Playgroud)

所以,此块用于配置"胶表"是必要的,因为在@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);
Run Code Online (Sandbox Code Playgroud)

  • *没必要*并不代表*不正确*.在配置中明确不会造成伤害,实际上很多次都有助于避免由隐式EF核心约定引起的意外.有要求提供一种摆脱所有约定的方法,并要求对所有内容进行显式配置. (5认同)
  • 如果在链接实体中使用[ForeignKey]属性,则不需要任何代码。即使这样:可悲的是,它不能像早期版本那样工作。在为Core开发的4年中,他们无法与以前的版本匹配。 (2认同)