Установка уникального ограничения с помощью fluent API?


Я пытаюсь построить сущность EF с кодом сначала, и EntityTypeConfiguration использование fluent API. создание первичных ключей легко, но не так с ограничением уникальности. Я видел старые сообщения, которые предлагали выполнять собственные команды SQL для этого, но это, похоже, не соответствует цели. возможно ли это с EF6?

6 168

6 ответов:

On помощью ef6.2, вы можете использовать HasIndex() чтобы добавить индексы для миграции через fluent API.

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

пример

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

On помощью ef6.1 далее, вы можете использовать IndexAnnotation() чтобы добавить индексы для миграции в вашем fluent API.

http://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex

вы необходимо добавить ссылку на:

using System.Data.Entity.Infrastructure.Annotations;

Простой Пример

вот простое использование, добавление индекса на User.FirstName свойства

modelBuilder 
    .Entity<User>() 
    .Property(t => t.FirstName) 
    .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));

Практический Пример:

вот более реалистичный пример. Он добавляет уникальный индекс по нескольким свойствам: User.FirstName и User.LastName, С именем индекса "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 }));

в дополнение к ответу Йорро, это также может быть сделано с помощью атрибутов.

образца int введите уникальную комбинацию клавиш:

[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }

[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }

если тип данных string, потом MaxLength атрибут должен быть добавлен:

[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; }

если существует проблема разделения модели домена / хранилища, используя Metadatatype атрибут/класс может быть вариант: https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx?f=255&MSPPError=-2147217396


быстрый пример консольного приложения:

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; }
    }
}

вот метод расширения для установки уникальных индексов более свободно:

public static class MappingExtensions
{
    public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
    {
        return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
    }
}

использование:

modelBuilder 
    .Entity<Person>() 
    .Property(t => t.Name)
    .IsUnique();

будет генерировать миграции, такие как:

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:создание уникального индекса с Entity Framework 6.1 fluent API

@coni2k ' s ответ правильный, однако вы должны добавить [StringLength] атрибут для его работы в противном случае вы получите недопустимое исключение ключа (пример ниже).

[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; }

к сожалению, это не поддерживается в Entity Framework. Это было на Дорожной карте для EF 6, но его отодвинули назад:Workitem 299: Уникальные Ограничения (Уникальные Индексы)