Définir une contrainte unique avec API fluent?

j'essaie de construire une entité EF avec Code D'abord, et un EntityTypeConfiguration en utilisant l'API fluent. créer des clés primaires est facile, mais pas avec une contrainte Unique. Je voyais de vieux messages qui suggéraient d'exécuter des commandes SQL natives pour ceci, mais qui semblent aller à l'encontre du but. est-ce possible avec EF6?

168
demandé sur abatishchev 2014-02-05 13:42:56

6 réponses

On EF6.2 , vous pouvez utiliser HasIndex() pour ajouter des index pour la migration par API fluent.

https://github.com/aspnet/EntityFramework6/issues/274

exemple

modelBuilder
    .Entity<User>()
    .HasIndex(u => u.Email)
        .IsUnique();

On EF6.À partir de 1 , vous pouvez utiliser IndexAnnotation() pour ajouter des index pour la migration dans votre API fluent.

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 un usage simple, en ajoutant un index sur la User.FirstName propriété

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 de multiples 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 }));
250
répondu Yorro 2017-12-28 19:18:49

comme un ajout à la réponse de Yorro, il peut également être fait en utilisant des attributs.

Échantillon int type unique combinaison de touche:

[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 y a 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


Une rapide application console exemple:

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; }
    }
}
132
répondu coni2k 2018-02-20 17:49:36

Voici une méthode d'extension pour définir les indices 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();

va générer 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: la Création d'Index Unique avec Entity Framework 6.1 API fluent

17
répondu Bartho Bernsmann 2017-05-23 12:02:39

la réponse de @coni2k est correcte mais vous devez ajouter l'attribut [StringLength] pour qu'il fonctionne sinon vous obtiendrez une exception de clé invalide (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; }
16
répondu Arijoon 2016-04-30 20:41:55

malheureusement, cela n'est pas pris en charge dans Entity Framework. Elle figurait sur la feuille de route de L'EF 6, mais elle a été repoussée: Workitem 299: unique Constraints (Unique Indexes)

10
répondu Kenneth 2014-02-05 11:59:19
0
répondu Shimmy 2014-04-02 01:47:06