EF Core反复创建相同的迁移,更改标识列,但未做任何更改

时间:2019-12-20 05:27:44

标签: ef-migrations ef-core-2.2

最近,我在EFCore2.2 DbContext中(在net47项目中)添加了一个新的数据实体,并尝试使用CLI工具生成迁移,因为我有很多次。尝试更新数据库时,迁移失败,因为迁移尝试对不相关表中的标识列进行ALTER COLUMN。我删除了迁移并删除了新实体,然后运行 add-migration ,基本上代码更改为零。确实,在Up&Down方法中生成了相同的中断AlterColumn调用,并且没有其他任何事情(看来毫无意义)。这是迁移代码:

public partial class ServerConfig : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<long>(
            name: "ID",
            table: "ProfileParams", 
            nullable: false,
            oldClrType: typeof(long))
            .OldAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<long>(
            name: "ID",
            table: "ProfileParams",
            nullable: false,
            oldClrType: typeof(long))
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    }
}

为了消除额外的因素,在最初添加此实体(ProfileParams)和创建迁移之后,我将代码恢复为 。从那时起,我尝试了 add-migration ,的确,我得到了与上面相同的迁移代码(快照没有变化)。然后,我将代码还原到添加了ProfileParams类之前的 之前,并生成了实际上是创建该表的迁移。它与完整的CREATE相同,并且快照已适当更改。但是之后,我立即再次运行了添加迁移。瞧,我得到了与上述相同的额外“更改列”迁移,并且下一次迁移将在下一次迁移中进行。

因此,从本质上讲,展望未来,似乎所有将来的迁移都将在up / down方法中添加相同的“更改列”。为什么?

为了获得更多细节:

  • 其他各种表都有一个ProfileParams导航属性,该属性 EFCore被选作可为空的外键。
  • 快照的缩写:
modelBuilder.Entity("ProfileParams", b =>
{
    b.Property<long>("ID")
        .ValueGeneratedOnAdd();
    b.HasKey("ID");
    b.ToTable("ProfileParams");
});

modelBuilder.Entity("AssetUser", b =>
{
    b.Property<string>("ID");
    b.Property<long?>("ParamsID");
    b.HasKey("ID");
    b.HasIndex("ParamsID");
    b.ToTable("AssetUsers");
});

modelBuilder.Entity("AssetUser", b =>
{
    b.HasOne("ProfileParams", "Params")
        .WithMany()
        .HasForeignKey("ParamsID");
});

2 个答案:

答案 0 :(得分:0)

问题是由于使用uint作为主键,并且看起来像是EF Core中的错误,它试图静默解决此问题,然后默默地以失败的方式失败。

在上述情况下,尽管我有详细信息,但我没有显示原始实体类,但所讨论的ID的确为uint类型。对其他问题的回答表明,EF Core不支持无​​符号类型,但肯定会假装,并造成这种情况的混乱!它会继续并创建它,而不是在初始迁移时出现错误(该错误不会为SQL自动身份应用所需的注释)。

这是我们期望的,如果实体类仅具有类型long的ID:

migrationBuilder.CreateTable(
    name: "ProfileParams",
    columns: table => new
    {
        ID = table.Column<long>(nullable: false)
/* But this part is missing when uint type is used! */
            .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_ProfileParams", x => x.ID);
    });

从那里开始,直到永远,在以后的所有迁移中,它将尝试通过更改带有注释的列来修复自己的遗漏。奇怪的是,即使它生成的“ Down”函数也暗示它已经已经,因为“ Up&Down”是相同的!但是原始迁移和快照以及所有后续快照无法捕获以下迁移尝试解决的问题。

大概是如果调整了迁移并且实际上删除了表并重新创建了表(不确定为什么EF Core认为它可以更改标识列!),那么生成的SQL表将具有自动标识bigint键,但是从该值填充实际的uint ID字段可能会出现问题。

简而言之,只需使用长键即可。哇!

答案 1 :(得分:0)

确保您只有一个提供程序的 NuGet 包。 我(在 MSSQL 旁边)还有 MySql 和 Postgresql,它在使用 AddMigration 时使用了错误的。