EF Core 2.0迁移-多对多以及其他字段 [英] EF Core 2.0 migration - Many-to-Many with additional fields

查看:262
本文介绍了EF Core 2.0迁移-多对多以及其他字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using EF Core 2.0 and created a many-to-many relationship with a join entity. When I add a new migration EF always creates an additional Index/Id-field which is completely stupid. Here is my join entity:

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上的几个示例):

This is the configuration of the join table (following several examples on the 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);
    }
}

为每个外键列迁移添加第二个:

For every foreign key columns migration adds a second one:

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

和两个完全相同的约束:

and two constraints which are absolutely identical:

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

我在这里做什么错了?

推荐答案

每当您看到EF(核心)生成其他FK列时,都清楚地表明使用错误的Fluent API重载导致未映射的引用或集合导航属性.所有相关的Fluent API(HasOneHasManyWithOneWithMany)都具有重载,并且没有导航属性.当相应实体没有导航时,必须使用第一个.并且,应使用 exact 来表示相应实体中是否存在导航属性.否则,将留下未映射的导航属性,而EF会创建其他关系.

Anytime you see EF (Core) generating additional FK columns, it's clear indication of unmapped reference or collection navigation property caused by the usage of a wrong fluent API overload. All related fluent API (HasOne, HasMany, WithOne, WithMany) have overloads with and w/o navigation property. You must use the first when the corresponding entity has no navigation And you should use the exact one representing the presence/absence of a navigation property in the corresponding entity. Failing to do so leaves unmapped navigation properties and EF creates additional relationships.

在您的情况下,两个差异(标记为A,B)在以下之间:

In your case, the two discrepancies (marked as A, B) are between:

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

如前所述,只需使其匹配即可:

As mentioned earlier, simply make them match:

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

问题消失了.

这篇关于EF Core 2.0迁移-多对多以及其他字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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