EF Core关联表创建异常:DbContext配置后迁移生成两张表
问题:EF Core生成两张多对多关联表且自定义配置未生效
我在代码中遇到了异常问题:创建了Place和SubCategory实体,因二者为多对多关系,手动创建了带复合键的PlaceSubCategory实体,并在DbContext中配置了如下DbSet:
public DbSet<PlaceSubCategory> PlaceSubCategories { get; set; }
但生成的迁移文件中却创建了两张表:一张是自定义的PlaceSubCategories表,另一张是自动生成的PlaceSubCategory表。同时,已通过modelBuilder应用的PlaceSubCategory配置类未生效,自定义的删除行为未被采用,自动生成的表使用了默认的级联删除。
迁移文件生成的代码如下:
migrationBuilder.CreateTable( name: "PlaceSubCategories", columns: table => new { PlaceId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), SubCategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), CreatedDateTime = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "getutcdate()") }, constraints: table => { table.PrimaryKey("PK_PlaceSubCategories", x => new { x.PlaceId, x.SubCategoryId }); table.ForeignKey( name: "FK_PlaceSubCategories_Places_PlaceId", column: x => x.PlaceId, principalTable: "Places", principalColumn: "PlaceId"); table.ForeignKey( name: "FK_PlaceSubCategories_SubCategories_SubCategoryId", column: x => x.SubCategoryId, principalTable: "SubCategories", principalColumn: "SubCategoryId"); }); migrationBuilder.CreateTable( name: "PlaceSubCategory", columns: table => new { PlacesPlaceId = table.Column<Guid>(type: "uniqueidentifier", nullable: false), SubCategoriesSubCategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false) }, constraints: table => { table.PrimaryKey("PK_PlaceSubCategory", x => new { x.PlacesPlaceId, x.SubCategoriesSubCategoryId }); table.ForeignKey( name: "FK_PlaceSubCategory_Places_PlacesPlaceId", column: x => x.PlacesPlaceId, principalTable: "Places", principalColumn: "PlaceId", onDelete: ReferentialAction.Cascade); table.ForeignKey( name: "FK_PlaceSubCategory_SubCategories_SubCategoriesSubCategoryId", column: x => x.SubCategoriesSubCategoryId, principalTable: "SubCategories", principalColumn: "SubCategoryId", onDelete: ReferentialAction.Cascade); });
自定义的PlaceSubCategory配置类代码如下:
public class PlaceSubCategoryConfiguration : IEntityTypeConfiguration<PlaceSubCategory> { public void Configure(EntityTypeBuilder<PlaceSubCategory> builder) { // define the composite key for PlaceSubCategory table builder.HasKey(x => new { x.PlaceId, x.SubCategoryId }); builder.HasOne<Place>(d => d.Place) .WithMany(d => d.SubCategoriesLink) .HasForeignKey(d => d.PlaceId) .OnDelete(DeleteBehavior.NoAction) .IsRequired(); builder.HasOne<SubCategory>(d => d.SubCategory) .WithMany(d => d.PlacesLink) .HasForeignKey(d => d.SubCategoryId) .OnDelete(DeleteBehavior.NoAction) .IsRequired(); builder.Property(p => p.CreatedDateTime) .HasConversion(AppDbContext.utcConverter) .HasDefaultValueSql("getutcdate()"); } }
且已通过以下代码应用配置:
modelBuilder.ApplyConfiguration(new PlaceSubCategoryConfiguration());
请问为何会生成两张表,且自定义配置未生效?
解答
核心原因
EF Core同时识别了两种多对多关系配置方式:
- 你手动创建的
PlaceSubCategory关联实体(显式多对多) - EF Core自动推断的隐式多对多关系(因为
Place和SubCategory实体中可能直接包含了对方的集合导航属性,比如Place.SubCategories或SubCategory.Places)
这两种配置冲突,导致EF Core生成了两张关联表:自动生成的PlaceSubCategory表来自隐式关系,而你的自定义配置只作用于显式的PlaceSubCategories表。
解决步骤
移除隐式多对多的导航属性
检查Place和SubCategory实体,删除直接指向对方实体的集合属性,只保留指向PlaceSubCategory的导航属性:public class Place { // 移除这类直接关联SubCategory的属性 // public ICollection<SubCategory> SubCategories { get; set; } public ICollection<PlaceSubCategory> SubCategoriesLink { get; set; } } public class SubCategory { // 移除这类直接关联Place的属性 // public ICollection<Place> Places { get; set; } public ICollection<PlaceSubCategory> PlacesLink { get; set; } }确认实体类字段完整性
确保PlaceSubCategory实体包含必要的字段和引用导航属性:public class PlaceSubCategory { public Guid PlaceId { get; set; } public Guid SubCategoryId { get; set; } public DateTime CreatedDateTime { get; set; } public Place Place { get; set; } public SubCategory SubCategory { get; set; } }清理并重新生成迁移
- 删除当前错误的迁移文件
- 执行
Remove-Migration(Package Manager Console)或dotnet ef migrations remove(CLI)回退到正确状态 - 重新执行
Add-Migration生成新迁移,此时只会生成PlaceSubCategories表,自定义的删除行为和字段配置也会生效。
内容的提问来源于stack exchange,提问作者CodingIsFunYouShouldTryIt
相关产品推荐
相关产品推荐

