与实体框架核心中同一实体的多对多关系

时间:2020-02-15 08:12:33

标签: c# asp.net-core entity-framework-core

当我实现两个类之间的多对多关系并使用流利的api配置其复合主键时,EF Core会在数据库中创建三列,而不是在数据库中创建两列。

UserReport.cs

public class UserReports
{
    public int ReporterId { get; set; }
    public User Reporter { get; set; }

    public int ReporteeId { get; set; }
    public User Reportee { get; set; }
}

User.cs

public class User: IdentityUser<int>
{
    public DateTime DateOfBirth { get; set; }
    public string KnownAs { get; set; }
    public DateTime Created { get; set; }
    public DateTime LastActive { get; set; }

    public ICollection<UserReports> Reporters { get; set; } = new Collection<UserReports>();
    public ICollection<UserReports> Reportees { get; set; } = new Collection<UserReports>();
}

ApplicatiobDbContext.cs

modelBuilder.Entity<UserReports>()
   .HasKey(ru => new { ru.ReporterId, ru.ReporteeId});

modelBuilder.Entity<UserReports>()
   .HasOne(ru => ru.Reportee)
   .WithMany(u => u.Reporters)
   .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<UserReports>()
   .HasOne(ru => ru.Reporter)
   .WithMany(u => u.Reportees)
   .OnDelete(DeleteBehavior.Restrict);

迁移

添加迁移后,EF核心将生成这种类型的迁移,这将创建额外的列

ReporterId1 = table.Column<int>(nullable: true)

migrationBuilder.CreateTable(
        name: "ReportUsers",
        columns: table => new
        {
           ReporterId = table.Column<int>(nullable: false),
           ReporteeId = table.Column<int>(nullable: false),
           ReporterId1 = table.Column<int>(nullable: true),
           Message = table.Column<string>(nullable: false)
        },

1 个答案:

答案 0 :(得分:1)

您在配置中缺少提到HasForeignKey的原因,这就是映射外键的困惑,因为它与实体相同是many-to-many。如下更新您的配置:

modelBuilder.Entity<UserReports>()
   .HasKey(ru => new { ru.ReporterId, ru.ReporteeId});

modelBuilder.Entity<UserReports>()
   .HasOne(ru => ru.Reportee)
   .WithMany(u => u.Reporters)
   .HasForeignKey(ru => ru.ReporteeId); // <-- Here it is
   .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<UserReports>()
   .HasOne(ru => ru.Reporter)
   .WithMany(u => u.Reportees)
   .HasForeignKey(ru => ru.ReporterId); // <-- Here it is
   .OnDelete(DeleteBehavior.Restrict);