EF Core 2.0 迁移 - 具有附加字段的多对多
EF Core 2.0 migration - Many-to-Many with additional fields
我正在使用 EF Core 2.0 并创建了一个与连接实体的多对多关系。当我添加一个新的迁移时,EF 总是创建一个额外的 Index/Id-field,这完全是愚蠢的。这是我的加入实体:
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; }
}
这是join的配置table(参考网上的几个例子):
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);
我做错了什么?
任何时候您看到 EF(核心)生成额外的 FK 列,都清楚地表明未映射的引用或集合导航 属性 是由于使用错误的流畅 API 重载造成的。所有相关的 fluent API(HasOne
、HasMany
、WithOne
、WithMany
)都有重载和 w/o 导航 属性。当相应的实体没有导航时,您必须使用第一个并且您应该使用 exact 表示相应实体中导航 属性 的 presence/absence。如果不这样做,将留下未映射的导航属性,并且 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);
问题解决了。
我正在使用 EF Core 2.0 并创建了一个与连接实体的多对多关系。当我添加一个新的迁移时,EF 总是创建一个额外的 Index/Id-field,这完全是愚蠢的。这是我的加入实体:
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; }
}
这是join的配置table(参考网上的几个例子):
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);
我做错了什么?
任何时候您看到 EF(核心)生成额外的 FK 列,都清楚地表明未映射的引用或集合导航 属性 是由于使用错误的流畅 API 重载造成的。所有相关的 fluent API(HasOne
、HasMany
、WithOne
、WithMany
)都有重载和 w/o 导航 属性。当相应的实体没有导航时,您必须使用第一个并且您应该使用 exact 表示相应实体中导航 属性 的 presence/absence。如果不这样做,将留下未映射的导航属性,并且 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);
问题解决了。