Generieren einer nicht nullbaren Zeilenversion unter SQL Server mit EF Core 3.1

Sep 02 2020

Wir versuchen, unter SQL Server mit EF Core 3.1 mithilfe der Fluent-API eine nicht nullbare Zeilenversionsspalte zu generieren:

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();
    }
}

Dies funktioniert gut, wenn die gesamte Tabelle neu ist:

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);
            });
    }
}

Manchmal müssen wir jedoch die Zeilenversion zu einer vorhandenen Tabelle hinzufügen. In diesem Fall generiert EF Core eine ungültige Migration:

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[] {  });
    }
}

Der oben generierte Standardwert verursacht eine Ausnahme, wenn er auf die Datenbank angewendet wird:

Fehler beim Ausführen von DbCommand (1 ms) [Parameters = [], CommandType = 'Text', CommandTimeout = '30 ']

ALTER TABLE [Personen] ADD [Timestamp] Zeilenversion NOT NULL DEFAULT 0x;

Microsoft.Data.SqlClient.SqlException (0x80131904): Für Spalten mit Datentyp-Zeitstempel können keine Standardwerte erstellt werden. Tabelle 'Personen', Spalte 'Zeitstempel'.
Einschränkung oder Index konnten nicht erstellt werden. Siehe vorherige Fehler.

Ist dies ein bekannter Fehler in EF Core? Das Problem kann durch manuelles Entfernen von defaultValue: new byte[] { }aus der Migration behoben werden. Gibt es jedoch eine Möglichkeit, die Generierung des Standardwerts mithilfe der Fluent-API zu unterdrücken?

Antworten

3 IvanStoev Sep 02 2020 at 17:57

Ist dies ein bekannter Fehler in EF Core?

Es ist sicher ein Fehler, aber wahrscheinlich nicht bekannt, da es sogar in der neuesten EF Core 5.0-Vorschau zu diesem Zeitpunkt auftritt. Oder ist bekannt, aber mit niedriger Priorität (für sie) - Sie müssen EF Core Issue Tracker überprüfen .

Versucht, explizit hinzuzufügen .HasDefaultValue(null)und .HasDefaultValueSql(null)- nichts hilft, daher ist die einzige Option das manuelle Entfernen der defaultValue: new byte[] { }aus der Migration. Das Gute ist, dass wenn Sie dies tun, es funktioniert und die Spalte erfolgreich erstellt und gefüllt wird, obwohl die Tabelle vorhandene Datensätze enthält (aus diesem Grund fügt EF Core ein solches defaultValueArgument für neue erforderliche Spalten im Allgemeinen hinzu, aber wie wir sehen, sollte dies nicht der Fall sein. ' t mach das für ROWVERSION).