使用 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
).
不应该这样做
我们正在尝试使用 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
).