EFCore 3 在每次迁移中为种子数据生成更新

EFCore 3 generate update for seed data in every migrations

将我的项目从 dotnet core 2.2 更新到 3.1 之后。现在,在 运行 migrations add 命令之后,新迁移包含所有种子数据的更新。

public class MyEntity
{
    public Guid Id { get; private set; }
    public string Code { get; private set; }
    public string Title { get; private set; }
    public bool IsActive { get; private set; }

    private MyEntity() { }

    [JsonConstructor]
    public MyEntity(Guid id, string code, string title)
    {
        Id = id;
        Title = title;
        Code = code;
        IsActive = true;
    }
}

public class MyEntityEntityTypeConfiguration
      : IEntityTypeConfiguration<MyEntity>
{
    public void Configure(EntityTypeBuilder<MyEntity> configuration)
    {
        configuration.HasKey(b => b.Id);

        configuration.Property(b => b.Title).HasMaxLength(150).IsRequired();

        configuration.Property(b => b.Code).HasMaxLength(20).IsRequired();

        configuration.Property(c => c.IsActive).HasDefaultValue(true);

        configuration.HasData(
            new MyEntity(new Guid("3274D8FD-DFAE-4396-8DD0-89A6F5107DB1"), "1", "titl1")
            );
    }
}

这是迁移中不需要的部分,此代码存在于所有功能迁移中。

        migrationBuilder.UpdateData(
            schema: "dbo",
            table: "MyEntity",
            keyColumn: "Id",
            keyValue: new Guid("08f2aa3d-ad4c-4a82-987c-ff43527466e0"),
            column: "IsActive",
            value: true);

我在更新到 dotnet core 3.1 之前没有这个更新。 有什么变化?

正在跟踪此问题 here

我在自己的项目中使用的解决方法是忽略所有 种子数据更新;

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "EF1001:Internal EF Core API usage.", Justification = "Workaround")]
    public class ModelDiffer : MigrationsModelDiffer
    {
        public ModelDiffer(
            IRelationalTypeMappingSource typeMappingSource, 
            IMigrationsAnnotationProvider migrationsAnnotations, 
            IChangeDetector changeDetector,
            IUpdateAdapterFactory updateAdapterFactory, 
            CommandBatchPreparerDependencies commandBatchPreparerDependencies) :
            base(typeMappingSource, migrationsAnnotations, changeDetector, updateAdapterFactory, commandBatchPreparerDependencies)
        {
        }
        //FIXME Remove when https://github.com/aspnet/EntityFrameworkCore/issues/18943 is deployed
        public override IReadOnlyList<MigrationOperation> GetDifferences(IModel source, IModel target)
        {
            return base.GetDifferences(source, target)
                    .Where(o => !(o is UpdateDataOperation))
                    .ToList();
        }
    }

    services.AddDbContextPool<Context>(o =>
    {
        o.ReplaceService<IMigrationsModelDiffer, ModelDiffer>();
        o.UseSqlServer(connectionString, ...
    }

在我的例子中,我不得不依赖 project issue 中建议的解决方法 - 确保每个默认值定义后也跟着 ValueGeneratedNever()。示例:

entity.Property(e => e.DateCreation)
    .HasColumnType("datetime")
    .HasDefaultValueSql("(getutcdate())")
    .ValueGeneratedNever();