J'essaie de créer une entité EF avec Code First et une EntityTypeConfiguration
en utilisant une API fluide. La création de clés primaires est facile, mais pas avec une contrainte unique. Je voyais d'anciens articles suggérant l'exécution de commandes SQL natives pour cela, mais cela semble aller à l'encontre du but recherché. est-ce possible avec EF6?
Sur EF6.2 , vous pouvez utiliser HasIndex()
pour ajouter des index pour la migration via une API fluide.
https://github.com/aspnet/EntityFramework6/issues/274
Exemple
modelBuilder
.Entity<User>()
.HasIndex(u => u.Email)
.IsUnique();
À partir de à partir de EF6.1 , vous pouvez utiliser IndexAnnotation()
pour ajouter des index de migration dans votre API courante.
http://msdn.Microsoft.com/en-us/data/jj591617.aspx#PropertyIndex
Vous devez ajouter une référence à:
using System.Data.Entity.Infrastructure.Annotations;
Exemple de base
Voici une utilisation simple, ajouter un index sur la propriété User.FirstName
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
Exemple pratique:
Voici un exemple plus réaliste. Il ajoute un index unique sur plusieurs propriétés: User.FirstName
et User.LastName
, avec un nom d'index "IX_FIrstNameLastName".
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true }));
modelBuilder
.Entity<User>()
.Property(t => t.LastName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));
En complément de la réponse de Yorro, vous pouvez également utiliser des attributs.
Exemple pour int
combinaison de clé unique:
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
Si le type de données est string
, l'attribut MaxLength
doit être ajouté:
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
S'il existe un problème de séparation de domaine/modèle de stockage, l'utilisation de Metadatatype
attribut/classe peut être une option: https://msdn.Microsoft.com/en-us/library/ff664465%28v=pandp .50% 29.aspx? F = 255 & MSPPError = -2147217396
Un exemple d'application de console rapide:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace EFIndexTest
{
class Program
{
static void Main(string[] args)
{
using (var context = new AppDbContext())
{
var newUser = new User { UniqueKeyIntPart1 = 1, UniqueKeyIntPart2 = 1, UniqueKeyStringPart1 = "A", UniqueKeyStringPart2 = "A" };
context.UserSet.Add(newUser);
context.SaveChanges();
}
}
}
[MetadataType(typeof(UserMetadata))]
public class User
{
public int Id { get; set; }
public int UniqueKeyIntPart1 { get; set; }
public int UniqueKeyIntPart2 { get; set; }
public string UniqueKeyStringPart1 { get; set; }
public string UniqueKeyStringPart2 { get; set; }
}
public class UserMetadata
{
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
}
public class AppDbContext : DbContext
{
public virtual DbSet<User> UserSet { get; set; }
}
}
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" });
}
}
Src: Création d'un index unique avec une API fluide Entity Framework 6.1
La réponse de @ coni2k est correcte, mais vous devez ajouter un attribut [StringLength]
pour que cela fonctionne, sinon vous obtiendrez une exception de clé non valide (exemple ci-dessous).
[StringLength(65)]
[Index("IX_FirstNameLastName", 1, IsUnique = true)]
public string FirstName { get; set; }
[StringLength(65)]
[Index("IX_FirstNameLastName", 2, IsUnique = true)]
public string LastName { get; set; }
Malheureusement, ceci n'est pas pris en charge dans Entity Framework. C'était sur la feuille de route pour EF 6, mais il a été repoussé: Workitem 299: Contraintes uniques (index uniques)
En attendant, il y a ceci:
Désolé de ne pas copier le code, c'est un peu long.