代码之家  ›  专栏  ›  技术社区  ›  okieh

EF Core 2.0迁移-多对多以及其他字段

  •  2
  • okieh  · 技术社区  · 8 年前

    我正在使用EF Core 2.0,并与join实体建立了多对多关系。当我添加新的迁移时,EF总是创建一个额外的索引/Id字段,这完全是愚蠢的。这是我的加入实体:

    public class Team_Member
    {
        public int TeamId { get; set; }
        public Team Team { get; set; }
    
        public int MemberId { get; set; }
        public Member Member { get; set; }
    
        public MemberTypeEnum MemberType { get; set; }
    }
    

    这是联接表的配置(以下是internet上的几个示例):

    public class Team_MemberConfig : IEntityTypeConfiguration<Team_Member>
    {
        public void Configure(EntityTypeBuilder<Team_Member> builder)
        {
            builder.ToTable("Team_Member");
            builder.HasKey(tm => new { tm.TeamId, tm.MemberId });
            builder.HasOne<Team>()
                .WithMany(t => t.Team_Member)
                .HasForeignKey(tm => tm.TeamId)
                .OnDelete(DeleteBehavior.Restrict);
            builder.HasOne<Member>()
                .WithMany(m => m.Team_Member)
                .HasForeignKey(tm => tm.MemberId)
                .OnDelete(DeleteBehavior.Restrict);
        }
    }
    

    对于每个外键列,迁移都会添加第二个外键列:

    columns: table => new
                {
                    TeamId = table.Column<int>(nullable: false),
                    MemberId = table.Column<int>(nullable: false),
                    **MemberId1** = table.Column<int>(nullable: true),
                    MemberType = table.Column<int>(nullable: false),
                    **TeamId1** = table.Column<int>(nullable: true)
                },
    

    以及两个完全相同的约束:

    table.ForeignKey(
                        name: "FK_Team_Member_Member_MemberId",
                        column: x => x.MemberId,
                        principalTable: "Member",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Team_Member_Member_MemberId1",
                        column: x => x.MemberId1,
                        principalTable: "Member",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Team_Member_Team_TeamId",
                        column: x => x.TeamId,
                        principalTable: "Team",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Team_Member_Team_TeamId1",
                        column: x => x.TeamId1,
                        principalTable: "Team",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
    

    我做错了什么?

    1 回复  |  直到 8 年前
        1
  •  4
  •   Ivan Stoev    8 年前

    无论何时,只要看到EF(Core)生成额外的FK列,就可以清楚地看到由于使用错误的fluent API重载而导致的未映射引用或集合导航属性。所有相关fluent API( HasOne , HasMany , WithOne , WithMany )具有带导航属性且不带导航属性的重载。当对应实体没有导航时,必须使用第一个,并且应该使用 准确的 一个表示相应实体中是否存在导航属性的属性。否则将留下未映射的导航属性,EF将创建其他关系。

    在您的情况下,两个差异(标记为A、B)介于:

    public class Team_Member
    {
        public int TeamId { get; set; }
        public Team Team { get; set; } // <-- A
    
        public int MemberId { get; set; }
        public Member Member { get; set; } // <-- B
    
        public MemberTypeEnum MemberType { get; set; }
    }
    

    builder.HasOne<Team>() // <-- A
        .WithMany(t => t.Team_Member)
        .HasForeignKey(tm => tm.TeamId)
        .OnDelete(DeleteBehavior.Restrict);
    builder.HasOne<Member>() // <-- B
        .WithMany(m => m.Team_Member)
        .HasForeignKey(tm => tm.MemberId)
        .OnDelete(DeleteBehavior.Restrict);
    

    如前所述,只需让它们匹配即可:

    builder.HasOne(tm => tm.Team) // <-- A
        .WithMany(t => t.Team_Member)
        .HasForeignKey(tm => tm.TeamId)
        .OnDelete(DeleteBehavior.Restrict);
    builder.HasOne(tm => tm.Member) // <-- B
        .WithMany(m => m.Team_Member)
        .HasForeignKey(tm => tm.MemberId)
        .OnDelete(DeleteBehavior.Restrict);
    

    问题已经解决了。