EF Core Fluent API HasData 在后续迁移中添加删除数据

EF Core Fluent API HasData adding delete data on subsequent migration

我正在使用 HasData 播种数据,它正在正确创建插入数据迁移脚本,但对于后续迁移,它会添加删除迁移而无需任何进一步更改。

实体

国家/地区

public class Country : BaseEntity
 {
     public string CountryName { get; set; }
 }

public class County : BaseEntity
{
    public string CountyName { get;set; }

    public int CountryId { get;set; }

    public Country Country { get; set; }
}

基础实体

public class BaseEntity
{ 
    public int Id { get; set; }

    public Guid ApplicationUserId { get; set; }
}

配置

public class CountyConfiguration : BaseEntityConfiguration<County>
{
    private const string TABLE_NAME = "Counties";

    public CountyConfiguration() : base(TABLE_NAME)
    {

    }

    public override void Configure(EntityTypeBuilder<County> entity)
    {
        base.Configure(entity);

        entity.Property(c => c.CountyName).IsRequired().HasMaxLength(100);
        entity.HasIndex(c => c.CountryId).IsUnique(false);
        entity.HasIndex(c => new {c.CountyName, c.CountryId }).IsUnique();
        entity.HasOne(c => c.Country).WithOne().OnDelete(DeleteBehavior.Cascade);

        entity.Ignore(c => c.ApplicationUserId);
        
        entity.HasData( 
            new County { Id = 1, CountryId = 1, CountyName = "Antrim"},
            new County { Id = 2, CountryId = 1, CountyName = "Carlow"},
            new County { Id = 3, CountryId = 1, CountyName = "Cavan"},
            new County { Id = 4, CountryId = 1, CountyName = "Clare"},
            new County { Id = 5, CountryId = 1, CountyName = "Cork"},
            new County { Id = 6, CountryId = 1, CountyName = "Derry (Londonderry)"},
            new County { Id = 7, CountryId = 1, CountyName = "Donegal"},
            new County { Id = 8, CountryId = 1, CountyName = "Dublin"},
            new County { Id = 9, CountryId = 1, CountyName = "Galway"},
            new County { Id = 10, CountryId = 1, CountyName = "Kerry"},
            new County { Id = 11, CountryId = 1, CountyName = "Kildare"},
            new County { Id = 12, CountryId = 1, CountyName = "Kilkenny"},
            new County { Id = 13, CountryId = 1, CountyName = "Laois (Queens)"},
            new County { Id = 14, CountryId = 1, CountyName = "Leitrim"},
            new County { Id = 15, CountryId = 1, CountyName = "Limerick"},
            new County { Id = 16, CountryId = 1, CountyName = "Longford"},
            new County { Id = 17, CountryId = 1, CountyName = "Louth"},
            new County { Id = 18, CountryId = 1, CountyName = "Mayo"},
            new County { Id = 19, CountryId = 1, CountyName = "Meath"},
            new County { Id = 20, CountryId = 1, CountyName = "Monaghan"},
            new County { Id = 21, CountryId = 1, CountyName = "Offaly (Kings)"},
            new County { Id = 22, CountryId = 1, CountyName = "Roscommon"},
            new County { Id = 23, CountryId = 1, CountyName = "Sligo"},
            new County { Id = 24, CountryId = 1, CountyName = "Tipperary"},
            new County { Id = 25, CountryId = 1, CountyName = "Waterford"},
            new County { Id = 26, CountryId = 1, CountyName = "Westmeath"},
            new County { Id = 27, CountryId = 1, CountyName = "Wexford"},
            new County { Id = 28, CountryId = 1, CountyName = "Wicklow"}
        );
    } 
}

生成的迁移 1:

public partial class County : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Counties",
            columns: table => new
            {
                Id = table.Column<int>(type: "int", nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                CountyName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
                CountryId = table.Column<int>(type: "int", nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("Pk_Counties_Id", x => x.Id);
                table.ForeignKey(
                    name: "FK_Counties_Countries_CountryId",
                    column: x => x.CountryId,
                    principalTable: "Countries",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.InsertData(
            table: "Counties",
            columns: new[] { "Id", "CountryId", "CountyName" },
            values: new object[,]
            {
                { 3, 1, "Cavan" },
                { 26, 1, "Westmeath" },
                { 25, 1, "Waterford" },
                { 24, 1, "Tipperary" },
                { 23, 1, "Sligo" },
                { 22, 1, "Roscommon" },
                { 21, 1, "Offaly (Kings)" },
                { 20, 1, "Monaghan" },
                { 19, 1, "Meath" },
                { 18, 1, "Mayo" },
                { 17, 1, "Louth" },
                { 16, 1, "Longford" },
                { 27, 1, "Wexford" },
                { 15, 1, "Limerick" },
                { 13, 1, "Laois (Queens)" },
                { 12, 1, "Kilkenny" },
                { 11, 1, "Kildare" },
                { 10, 1, "Kerry" },
                { 9, 1, "Galway" },
                { 8, 1, "Dublin" },
                { 7, 1, "Donegal" },
                { 6, 1, "Derry (Londonderry)" },
                { 5, 1, "Cork" },
                { 4, 1, "Clare" },
                { 2, 1, "Carlow" },
                { 14, 1, "Leitrim" },
                { 28, 1, "Wicklow" }
            });

        migrationBuilder.CreateIndex(
            name: "IX_Counties_CountryId",
            table: "Counties",
            column: "CountryId");

        migrationBuilder.CreateIndex(
            name: "IX_Counties_CountyName_CountryId",
            table: "Counties",
            columns: new[] { "CountyName", "CountryId" },
            unique: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Counties");
    }
}

下一次迁移 2:(无任何更改)

public partial class Empty : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DeleteData(
            table: "Counties",
            keyColumn: "Id",
            keyValue: 1);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DeleteData(
            table: "Counties",
            keyColumn: "Id",
            keyValue: 1);

        migrationBuilder.InsertData(
            table: "Counties",
            columns: new[] { "Id", "CountryId", "CountyName" },
            values: new object[] { 1, 1, "Antrim" });
    }
}

不确定,为什么要添加 migrationBuilder.DeleteData 删除脚本?

这里

entity.HasOne(c => c.Country).WithOne().OnDelete(DeleteBehavior.Cascade);

with WithOne() 你基本上是在告诉 EF County.CountryId 必须是唯一的(因为关系数据库中一对一和一对多之间的唯一区别是唯一约束FK 列的(索引)。

然而,在此之前你告诉 EF 相反

entity.HasIndex(c => c.CountryId).IsUnique(false);

这一系列相互冲突的配置以某种方式混淆了 EF,它开始做一些奇怪的事情。

虽然这可以被认为是他们的错误,但最终问题出在您的代码中,因为显然您不想要一对一的关系。因此,通过将 HasOne 替换为 HasMany

来更正
entity.HasOne(c => c.Country).WithMany().OnDelete(DeleteBehavior.Cascade);

或完全删除它,因为它所做的一切都与默认的 EF Core 约定相同。

完成后,您还可以删除 HasIndex 配置,因为它也是 EF Core FK 索引约定的默认配置。