Generazione di rowversion non nullable in SQL Server con EF Core 3.1
Stiamo cercando di generare una colonna rowversion non annullabile su SQL Server con EF Core 3.1 utilizzando l'API Fluent:
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();
}
}
Funziona bene quando l'intera tabella è nuova:
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);
});
}
}
Tuttavia, a volte è necessario aggiungere rowversion a una tabella esistente. In tal caso, EF Core genera una migrazione non valida:
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[] { });
}
}
Il valore predefinito generato sopra causerà un'eccezione quando viene applicato al database:
Impossibile eseguire DbCommand (1 ms) [Parameters = [], CommandType = 'Text', CommandTimeout = '30 ']
ALTER TABLE [Persone] ADD [Timestamp] rowversion NOT NULL DEFAULT 0x;
Microsoft.Data.SqlClient.SqlException (0x80131904): i valori predefiniti non possono essere creati sulle colonne di tipo di dati timestamp. Tabella "Persone", colonna "Timestamp".
Impossibile creare vincolo o indice. Vedi errori precedenti.
È un bug noto in EF Core? Il problema può essere risolto rimuovendo manualmente il defaultValue: new byte[] { }dalla migrazione, ma esiste un modo per eliminare il valore predefinito dalla generazione utilizzando l'API Fluent?
Risposte
È un bug noto in EF Core?
È sicuramente un bug / difetto, ma probabilmente non è noto, dal momento che sta accadendo anche nell'ultima anteprima di EF Core 5.0 in questo momento. O è noto, ma con bassa priorità (per loro): devi controllare EF Core Issue Tracker .
Ho provato ad aggiungere esplicitamente .HasDefaultValue(null)e .HasDefaultValueSql(null)- niente aiuta, quindi l'unica opzione è rimuovere manualmente il defaultValue: new byte[] { }dalla migrazione. La cosa buona è che quando lo fai, funziona e la colonna viene creata e popolata correttamente anche se la tabella ha record esistenti (che è il motivo per cui EF Core aggiunge tale defaultValueargomento per le nuove colonne obbligatorie in generale, ma come vediamo non dovrebbe ' farlo per ROWVERSION).