J'ai une colonne "Nom" qui doit être unqiue. Aucune clé étrangère ou quelque chose comme ça.
EF 6.1 prend enfin en charge la création de tels index via Annotations. Cela a déjà été discuté sur SO. Mais il semble que cela ne peut se faire que par des annotations dans les classes. Comment est-ce que je fais cela en utilisant seulement l'API Fluent?
Quelque chose comme ça:
public class PersonConfiguration : EntityTypeConfiguration<Person>
{
public PersonConfiguration()
{
HasKey(p => p.Id);
Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
//not possible?
Index(p => p.Name).IsUnique(); //???
}
}
NOTE: Pertinent pour EF 6
Vous pouvez utiliser IndexAttribute
comme mentionné mais avec Fluent API
au lieu de DataAnnotations
qui fera l'affaire:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.HasColumnAnnotation(
"Index",
new IndexAnnotation(new IndexAttribute("IX_Name") { IsUnique = true }));
Malheureusement, il n'y a pas d'autre moyen de créer des index uniques en utilisant Fluent API
. Il existe un problème en suspens concernant cette fonctionnalité: Contraintes uniques (index uniques)
Fluent API
pour spécifier des index sans astuces supplémentaires. HasIndex
permet de le définir:modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name);
Par conséquent, il reprend l'objet IndexBuilder
, vous pouvez l'utiliser pour d'autres configurations d'index (par exemple, l'unicité):
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name)
.IsUnique();
Basé sur la réponse d'Anatolii, voici une méthode d'extension pour définir plus facilement des index uniques:
public static class MappingExtensions
{
public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
{
return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
}
}
Usage:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.IsUnique();
Générera une migration telle que:
public partial class Add_unique_index : DbMigration
{
public override void Up()
{
CreateIndex("dbo.Person", "Name", unique: true);
}
public override void Down()
{
DropIndex("dbo.Person", new[] { "Name" });
}
}
Cette réponse ne contient que des informations supplémentaires car il existe déjà d'excellentes réponses.
Si vous voulez avoir plusieurs champs uniques dans votre index, vous pouvez le réaliser en ajoutant la propriété Order
. Vous devez également vous assurer que vous utilisez le même nom d'index dans toutes vos propriétés (voir uniqueIndex
ci-dessous).
string uniqueIndex = "UN_TableName";
this.Property(t => t.PropertyOne)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute(uniqueIndex)
{
IsUnique = true,
Order = 1
}
)
);
this.Property(t => t.PropertyTwo)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute(uniqueIndex)
{
IsUnique = true,
Order = 2
}
)
);
Supposons maintenant que vous souhaitiez également un index sur PropertyTwo
.
La méthode mal consiste à démarrer une ligne nouvelle _ avec this.Property(t => t.PropertyTwo)
, comme ANNULER votre index unique.
Tous vos index (index et unique) doivent être définis en même temps. Ce serait la bonne façon de le faire:
this.Property(t => t.PropertyTwo)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(new[]
{
new IndexAttribute(), // This is the index
new IndexAttribute(uniqueIndex) // This is the Unique made earlier
{
IsUnique = true,
Order = 2
}
}
)
);
Enfin, si vous souhaitez également modifier l'ordre de tri de votre index/unique, vous pouvez voir:
Comment ajouter un index sur plusieurs colonnes avec le tri ASC/DESC à l'aide de l'API Fluent? .
Dans la nouvelle version de EF, 6.2, vous pouvez utiliser la méthode HasIndex
:
modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);
Mise à jour pour EF Core:
modelBuilder.Entity<User>()
.HasIndex(b => b.Email)
.IsUnique();
modelBuilder.Entity<User>()
.HasIndex(b => b.UserName)
.IsUnique();
Vous pouvez créer un index unique dans votre fichier de migration.
Dans le gestionnaire de paquets:
Cela créera un nouveau fichier horodaté dans votre dossier Migrations. La classe aura une méthode Up and Down que vous pouvez utiliser pour créer l'index:
public override void Up()
{
// ...
CreateIndex("tableName", "columnName", unique: true, name: "myIndex");
}
public override void Down()
{
// ...
DropIndex("tableName", "myIndex");
}
Pour exécuter la migration, tapez Update-Database dans le gestionnaire de packages.
Vous pouvez également ajouter l'index dans le cadre de la migration qui crée la table:
CreateTable(
"dbo.Products",
c => new
{
ProductId = c.Int(nullable: false, identity: true),
ProductName = c.String(nullable: false, maxLength: 256),
})
.Index(c => c.ProductName, name: "IX_Products_ProductName", unique: true)
.PrimaryKey(t => t.ProductId);
Pour moi, en utilisant MVC 5 et EF 6, le point clé était de spécifier une longueur sur la propriété de chaîne où je voulais placer l'index.
protected override void OnModelCreating(DbModelBuilder modelBuilder){
//More stuff
modelBuilder.Entity<Device>().Property(c => c.Name).HasColumnType("nvarchar").HasMaxLength(50);
modelBuilder.Entity<Device>().HasIndex(c => c.Name).IsUnique(true);
}