web-dev-qa-db-fra.com

EF 6.1 Indice Nullable Unique

Dans EF 6.1 en utilisant Code First, vous pouvez créer des index en utilisant des attributs dans vos entités ou en utilisant l’API fluide le long des lignes suivantes:

 Property(x => x.PropertyName)
                .IsOptional()
                .HasMaxLength(450)
                .HasColumnAnnotation("Index",
                    new IndexAnnotation(new IndexAttribute("IX_IndexName") {IsUnique = true,  }));

Est-il possible de dire échafaudage WHERE PropertyName IS NOT NULL de la même manière que dans SQL Server en mode natif (voir: https://stackoverflow.com/a/767702/52026 )?

40
MrEdmundo

Je n'ai pas trouvé le moyen de dire à EF d'utiliser cette clause where, mais voici une solution de contournement. Vérifiez si cela convient à votre cas.

  1. Installez Entity Framework, définissez votre DbContext, vos entités, votre chaîne de connexion dans app.config, etc.
  2. Activer la migration - exécuté dans la console de gestion de package '-EnableMigration'
  3. Créer DbMigration - exécuté dans la console Add-Migration MigrationName de la console du gestionnaire de packages
  4. Dans la classe DbMigration créée dans la méthode Up de ovverided, exécutez votre SQL pour créer un index nullable unique.

code:

// Add unique nullable index 
string indexName = "IX_UQ_UniqueColumn";
string tableName = "dbo.ExampleClasses";
string columnName = "UniqueColumn";

Sql(string.Format(@"
    CREATE UNIQUE NONCLUSTERED INDEX {0}
    ON {1}({2}) 
    WHERE {2} IS NOT NULL;",
    indexName, tableName, columnName));

Remarque: n'oubliez pas de créer également une rétrogradation. Méthode Ovveride Down et utilisation de la méthode DropIndex à l'intérieur de:

DropIndex(tableName, indexName);

De plus, vous aurez peut-être besoin de code supplémentaire si la base de données contient déjà des données susceptibles d'entrer en conflit avec la contrainte d'index unique.

Remarque: Ici, vous pouvez utiliser la méthode CreateIndex mais je ne pouvais pas créer le bon index avec elle. EF ignore simplement mes arguments anonymes ou je les écrit mal. Vous pouvez l'essayer vous-même et écrire ici avec votre résultat. La syntaxe est la suivante:

CreateIndex(
    table: "dbo.ExampleClasses",
    columns: new string[] { "UniqueColumn" },
    unique: true,
    name: "IX_UniqueColumn",
    clustered: false,
    anonymousArguments: new
    {
        Include = new string[] { "UniqueColumn" },
        Where = "UniqueColumn IS NOT NULL"
    });

</ strike> 5 Essayez d'ajouter deux etries avec des valeurs nulles pour la colonne unique et d'autres valeurs égales.

Voici mon code de démonstration - Pastebin

46
Viktor Bahtev

Dans EF Core, vous pouvez utiliser la méthode HasFilter dans l’API fluide pour obtenir ce que vous recherchez sans ajouter de code SQL personnalisé à la migration.

builder.Entity<Table>()
    .HasIndex(x => x.PropertyName)
    .HasName("IX_IndexName")
    .HasFilter("PropertyName IS NOT NULL");

Cela génère une migration comme ceci:

migrationBuilder.CreateIndex(
    name: "IX_IndexName",
    table: "Table",
    columns: new[] { "PropertyName" },
    filter: "PropertyName IS NOT NULL");
0
Sam