Création D'un Index Unique avec Entity Framework 6.1 API fluide
J'ai une colonne "Name" qui doit être unqiue. Pas de clé étrangère ou quelque chose comme ça.
EF 6.1 prend enfin en charge la création de tels Index via des Annotations. Cela a déjà été discuté sur SO. Mais il semble que cela ne peut être fait que via des annotations dans les classes. Comment puis-je faire cela en utilisant uniquement L'API Fluent?
Quelque Chose comme ceci:
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(); //???
}
}
6 réponses
REMARQUE: Les 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 y a un problème ouvert concernant cette fonctionnalité: contraintes uniques (index uniques)
mise à jour: Entity Framework Core
Dans la dernière version D'EF Core, vous pouvez compter sur
Fluent API
pour spécifier des index sans autres trucs.
HasIndex
permet de définir:
modelBuilder
.Entity<Person>()
.HasIndex(x => x.Name);
Par conséquent, il retourne l'objet IndexBuilder
Vous pouvez l'utiliser pour d'autres configurations d'index (c'est-à-dire 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 des index uniques plus couramment:
public static class MappingExtensions
{
public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
{
return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
}
}
Utilisation:
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à de bonnes réponses.
Si vous voulez avoir plusieurs champs uniques dans votre index, vous pouvez y parvenir 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
}
)
);
Maintenant, disons que vous voulez aussi un index sur PropertyTwo
.
Le mal façon de le faire serait de commencer un nouveaux ligne this.Property(t => t.PropertyTwo)
comme cela annulerait 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 aussi vous souhaitez modifier l'ordre de tri de votre index/unique, vous pouvez voir :
Comment ajouter un index sur plusieurs colonnes avec le tri ASC/DESC en utilisant L'API Fluent ?.
Dans la nouvelle version de EF qui est 6.2 vous pouvez utiliser HasIndex
méthode:
modelBuilder.Entity<User>().HasIndex(user => user.Email).IsUnique(true);
modelBuilder.Entity<User>().HasIndex(user => user.UserName).IsUnique(true);
Mise à Jour Pour EF de Base:
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:
- Activer-Migrations
- Ajouter-Migration InitialMigration
Cela va créer un nouveau fichier dans votre dossier Migrations qui est horodaté. La classe aura une méthode Up et une méthode 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 le type de migration Update-Database dans le gestionnaire de paquets.
Vous pouvez également ajouter l'index dans le cadre de la migration crée également 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é string 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);
}