首页 > 解决方案 > Entity Framework Core 中同一个实体的多对多关系

问题描述

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

用户报告.cs

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

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

用户.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>();
}

应用程序数据库上下文.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)
        },

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

解决方案


您在配置中缺少提及,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);

推荐阅读