Génération de rowversion non nullable sur SQL Server avec EF Core 3.1

Sep 02 2020

Nous essayons de générer une colonne rowversion non nullable sur SQL Server avec EF Core 3.1 à l'aide de 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();
    }
}

Cela fonctionne bien lorsque la table entière est nouvelle:

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

Cependant, nous devons parfois ajouter la rowversion à une table existante. Dans ce cas, EF Core génère une migration non valide:

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

La valeur par défaut générée ci-dessus provoquera une exception lors de son application à la base de données:

Échec de l'exécution de DbCommand (1ms) [Parameters = [], CommandType = 'Text', CommandTimeout = '30 ']

ALTER TABLE [Personnes] ADD [Horodatage] rowversion NOT NULL DEFAULT 0x;

Microsoft.Data.SqlClient.SqlException (0x80131904): les valeurs par défaut ne peuvent pas être créées sur les colonnes d'horodatage de type de données. Tableau 'Personnes', colonne 'Horodatage'.
Impossible de créer une contrainte ou un index. Voir les erreurs précédentes.

S'agit-il d'un bogue connu dans EF Core? Le problème peut être résolu en supprimant manuellement le defaultValue: new byte[] { }de la migration, mais existe-t-il un moyen de supprimer la valeur par défaut de la génération à l'aide de l'API Fluent?

Réponses

3 IvanStoev Sep 02 2020 at 17:57

S'agit-il d'un bogue connu dans EF Core?

Il s'agit d'un bug / défaut à coup sûr, mais probablement inconnu, car cela se produit même dans la dernière préversion EF Core 5.0. Ou est connu, mais avec une faible priorité (pour eux) - vous devez vérifier EF Core Issue Tracker .

J'ai essayé d'ajouter explicitement .HasDefaultValue(null)et .HasDefaultValueSql(null)- rien n'y fait, donc la seule option consiste à supprimer manuellement le defaultValue: new byte[] { }de la migration. La bonne chose est que lorsque vous le faites, cela fonctionne et la colonne est créée et remplie avec succès même si la table contient des enregistrements existants (ce qui est la raison pour laquelle EF Core ajoute un tel defaultValueargument pour les nouvelles colonnes requises en général, mais comme nous le voyons, ne devrait pas t fais ça pour ROWVERSION).