使用 EF Core 3.1 在 SQL 服务器上生成不可为 null 的行版本

Generating non-nullable rowversion on SQL Server with EF Core 3.1

我们正在尝试使用 Fluent API 在具有 EF Core 3.1 的 SQL 服务器上生成不可为 null 的 rowversion 列:

public class Person
{
    public int Id { get; set; }
    public byte[] Timestamp { get; set; }
}

public class PersonEntityConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.HasKey(p => p.Id);

        builder.Property(p => p.Timestamp)
            .IsRowVersion()
            .IsRequired();
    }
}

当整个 table 是新的时,这工作正常:

public partial class PersonMigration : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Persons",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:Identity", "1, 1"),
                Timestamp = table.Column<byte[]>(rowVersion: true, nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Persons", x => x.Id);
            });
    }
}

但是,我们有时需要将行版本添加到现有 table。在这种情况下,EF Core 会生成无效迁移:

public partial class PersonTimestampMigration : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<byte[]>(
            name: "Timestamp",
            table: "Persons",
            rowVersion: true,
            nullable: false,
            defaultValue: new byte[] {  });
    }
}

上面生成的默认值在应用到数据库时会出现异常:

Failed executing DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']

ALTER TABLE [Persons] ADD [Timestamp] rowversion NOT NULL DEFAULT 0x;

Microsoft.Data.SqlClient.SqlException (0x80131904): Defaults cannot be created on columns of data type timestamp. Table 'Persons', column 'Timestamp'.
Could not create constraint or index. See previous errors.

这是 EF Core 中的已知错误吗?可以通过从迁移中手动删除 defaultValue: new byte[] { } 来解决此问题,但是有没有一种方法可以抑制使用 Fluent API?

生成默认值

Is this a known bug in EF Core?

肯定是 bug/defect,但可能不知道,因为它甚至出现在最新的 EF Core 5.0 预览版中。或者是已知的,但优先级较低(对他们而言)- 您必须检查 EF Core Issue Tracker.

尝试显式添加 .HasDefaultValue(null).HasDefaultValueSql(null) - 没有任何帮助,因此唯一的选择是从迁移中手动删除 defaultValue: new byte[] { }。好消息是,当您这样做时,即使 table 有现有记录,它也会成功创建和填充该列(这就是 EF Core 为新的必需列添加这样的 defaultValue 参数的原因一般而言,但正如我们所见, ROWVERSION).

不应该这样做