유창한 API로 고유 한 제약 조건을 설정 하시겠습니까?


185

Code First 및 EntityTypeConfiguration유창한 API를 사용하여 EF 엔티티를 작성하려고합니다 . 고유 제한 조건으로는 기본 키를 작성하는 것이 쉽지만 그렇지 않습니다. 나는 이것을 위해 네이티브 SQL 명령 실행을 제안하는 오래된 게시물을 보았지만 그 목적을 어기는 것 같습니다. EF6에서 가능합니까?

답변:


275

EF6.2 , 당신은 사용할 수 있습니다 HasIndex()유창하게 API를 통해 마이그레이션에 대한 인덱스를 추가 할 수 있습니다.

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

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

EF6.1 이후, 당신이 사용할 수있는 IndexAnnotation()귀하의 유창한 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.FirstNameUser.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 }));

4
열 주석의 이름을 "Index"로 지정해야합니다! 다른 이름을 썼는데 작동하지 않았습니다! 게시물에서와 같이 원래 '색인'으로 이름을 바꾸는 데 몇 시간을 보냈으며 이것이 중요하다는 것을 이해했습니다. :( 프레임 워크에는 문자열을 하드 코딩하지 않는 상수가 있어야합니다.
Alexander Vasilyev

10
@AlexanderVasilyev 상수는 다음과 같이 정의됩니다.IndexAnnotation.AnnotationName
Nathan

3
@Nathan 감사합니다! 그게 다야! 이 게시물의 예제는이 상수를 사용하여 수정해야합니다.
Alexander Vasilyev

2
EF7에서 찾을 수없는 것-DNX
Shimmy Weitzhandler

2
첫 번째 예제에서 IndexAttribute를 만들 때 IsUnique를 true로 설정해야한다고 생각합니다. 이와 같이 : new IndexAttribute() { IsUnique = true }. 그렇지 않으면 일반 (고유하지 않은) 인덱스 만 생성합니다.
jakubka

134

Yorro의 답변 외에도 속성을 사용하여 수행 할 수도 있습니다.

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

45
도메인 모델을 스토리지 문제와 완전히 분리하지 않으려면 아닙니다.
Rickard Liljeberg

4
당신은 또한 당신이 EntityFramework에 대한 참조가 있는지 확인해야합니다
마이클 Tranchida

2
Index 속성이 Entity Framework와 분리되어 모델 프로젝트에 포함시킬 수 있다면 좋을 것입니다. 스토리지 관련 문제라는 것을 알고 있지만이를 사용하는 주된 이유는 UserNames 및 Role Names에 고유 한 제약 조건을 적용하기 때문입니다.
Sam

2
EF7에서 찾을 수없는 것-DNX
Shimmy Weitzhandler

4
SQL에서는 nvarchar (max) 를 키로 사용할 수 없으므로 문자열 길이도 제한하는 경우에만 작동합니다 .
JMK

17

고유 색인을보다 유창하게 설정하는 확장 방법은 다음과 같습니다.

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 유창 API를 사용하여 고유 인덱스 생성


16

@ coni2k의 답변은 정확하지만 [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; }


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.