尽管没有进行任何更改,为什么EF Core仍会在每次迁移时都更新种子布尔字段?

问题描述

这是EF Core 3.1。我有几个带有布尔字段IsActive的模型,定义如下:

public class Job
{
    public bool? IsActive { get; set; }
}

我的种子数据如下:

modelBuilder.Entity<Job>()
    .Property(e => e.IsActive)
    .HasDefaultValue(true);

modelBuilder.Entity<Job>().HasData(
    new Job() { IsActive = true });

每次创建迁移时(包括如果我进行的迁移都没有进行任何更改,这会产生一个空的迁移),它将对上面的字段进行UpdateData调用,如下所示:

migrationBuilder.UpdateData(
    table: "Jobs",keyColumn: "id",keyvalue: 1L,column: "IsActive",value: true);

我还在TodoApi appsetup a GitHub repo中向对更多细节感兴趣的人复制了此行为。

我了解that happening when the seed data is being generated by a function或类似DateTime.Now之类的结果。我不知道在播种期间为该列分配了原始布尔值时会发生这种情况。

此行为似乎与issue #13047非常相似,“将BoolToStringConverter与HasData一起使用时生成了不正确的UpdateData操作”,但问题为was fixed in EF Core 2.2

解决方法

原因是下面的模型配置代码中的HasDefaultValue(true)调用-

modelBuilder.Entity<Job>()
    .Property(e => e.IsActive)
    .HasDefaultValue(true);

每当您使用HasDefaultValue()方法为属性设置默认值时,那个就是要为数据库表中相应列设置的值。

使用HasDefaultValue(true),您已将true设置为IsActive属性的默认值。因此,在种子数据中-

modelBuilder.Entity<Job>().HasData(
    new Job() { IsActive = true });

将值设置为IsActive(无论值是什么都无关紧要),从迁移的角度来看是一种变化,即使数据在两次迁移之间没有变化。

编辑-解决方案:
设置列默认值的要求始终是有效要求。因此,您可能要考虑更改的另一件事是数据播种方法。

您现在使用的播种方法完全由迁移本身管理,并且有一些限制-Limitations of model seed data

您可以使用Custom initialization logic播种与迁移无关的数据。