먼저 EF 코드를 사용하여 복합 키 매핑


115

SQL 서버 테이블 :

SomeId PK varchar(50) not null 
OtherId PK int not null

EF 6 코드에서이를 먼저 매핑하려면 어떻게해야합니까?

public class MyTable
{
    [Key]
    public string SomeId { get; set; }

    [Key]
    public int OtherId { get; set; }
}

각 열의 순서를 설정해야하는 몇 가지 예를 보았습니다. 필수입니까?

어딘가에 공식 문서가 있습니까?


가 또는은 ? SomeIdstringint
Corey Adler 2013

@ IronMan84 그것은 문자열입니다, 나는 그것을 고칠 것입니다.
loyalflow

답변:


187

열 순서를 반드시 입력해야합니다. 그렇지 않으면 SQL Server가 어느 것이 먼저 진행되는지 어떻게 알 수 있습니까? 코드에서 수행해야 할 작업은 다음과 같습니다.

public class MyTable
{
  [Key, Column(Order = 0)]
  public string SomeId { get; set; }

  [Key, Column(Order = 1)]
  public int OtherId { get; set; }
}

이 SO 질문을 볼 수도 있습니다 . 공식 문서를 원하신다면 EF 공식 웹 사이트를 참조 하시기 바랍니다 . 도움이 되었기를 바랍니다.

편집 : 방금 Julie Lerman의 모든 종류의 EF 6 장점에 대한 링크가있는 블로그 게시물을 찾았습니다. 여기에서 필요한 것을 찾을 수 있습니다 .


EntityConfiguration을 통해 어떻게 수행합니까? 실제로 조인 테이블에 대한 엔터티가 없습니다 ... 매핑을 설정하기 위해 두 엔터티와 그중 하나에 .Map ()을 사용하여 EntityConfiguration이 있습니다.
미르

31
otherwise how is SQL Server supposed to know which one goes first?-다른 모든 열의 순서를 아는 것과 같은 방식이 아닌 이유는 무엇입니까?
Davor

1
EF는 다른 열의 순서를 알지 못하므로 이름이 지정되어있는 한 원하는 순서로 열을 삽입 할 수 있습니다. EF에서 복합 PK에 대한 주문이 필요한 경우 인덱싱과 관련되어야합니다.
Sylvain Gantois

@Davor EF 제작자가 리플렉션을 사용하여 키 / 열 순서를 추론 할 수 있었을 것이라고 생각합니다. 그러나이를 수행하지 않는 데 대한 성능 고려 사항이있을 수 있습니다. 특히 DAL에서 느린 성능보다 디자인 타임 특이성을 고려할 것입니다.
Jacob Stamm

47

엔티티 프레임 워크를 사용하는 복합 기본 키 매핑의 경우 두 가지 접근 방식을 사용할 수 있습니다.

1) OnModelCreating () 메서드 재정의

예를 들어 : 아래와 같이 VehicleFeature라는 모델 클래스가 있습니다.

public class VehicleFeature
{
    public int VehicleId { get; set; }
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

내 DBContext의 코드는 다음과 같습니다.

public class VegaDbContext : DbContext
{
    public DbSet<Make> Makes{get;set;}

    public DbSet<Feature> Features{get;set;}
    public VegaDbContext(DbContextOptions<VegaDbContext> options):base(options)        
    {           

    }
    // we override the OnModelCreating method here.
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VehicleFeature>().HasKey(vf=> new {vf.VehicleId, vf.FeatureId});
    }
}

2) 데이터 주석으로.

public class VehicleFeature
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
    [Key]
    public int VehicleId { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
    [Key]
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

자세한 내용은 아래 링크를 참조하십시오.

1) https://msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx

2) EF 6 Fluent Api를 사용하여 복합 고유 키를 추가하는 방법은 무엇입니까?


5
FYI for EF Core, Option # 2 is not possible , "복합 키는 Fluent API를 사용해서 만 구성 할 수 있습니다. 규칙은 복합 키를 설정하지 않으며 데이터 주석을 사용하여 구성 할 수 없습니다."
Tobias J

7

구성을 통해 다음을 수행 할 수 있습니다.

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

그런 다음 컨텍스트 구성에서

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Model1>()
            .HasRequired(e => e.Model2)
            .WithMany(e => e.Model1s)
            .HasForeignKey(e => new { e.fk_one, e.fk_two })
            .WillCascadeOnDelete(false);
    }
}

컨텍스트 구성에서 어디에 있습니까?
Charlie

Fluent API를 사용하여 코드를 통해 컨텍스트를 구성하는 경우 ... 섹션 7 . public class MyContext : DbContext {protected override void OnModelCreating (DbModelBuilder modelBuilder) {modelBuilder.Entity <Model1> () .HasRequired (e => e.Model2) .WithMany (e => e.Model1s) .HasForeignKey (e => new {e.fk_one, e.fk_two}) .WillCascadeOnDelete (false); }}
philn5d

dotnet core에서 DbModelBuilder 대신 ModelBuilder를 사용해야한다는 것을 알았습니다.
kiml42

6

이 질문이 상위 Google 검색 결과이므로이 질문에 추가 할 것이라고 생각했습니다.

주석에서 언급했듯이 EF Core에서는 주석 (Key 특성) 사용을 지원하지 않으며 유창하게 수행해야합니다.

EF6에서 EF Core 로의 대규모 마이그레이션을 작업 할 때 이것은 비정상적이었고 리플렉션을 사용하여 Key 특성을 찾은 다음 OnModelCreating 중에 적용하여 해킹하려고했습니다.

// get all composite keys (entity decorated by more than 1 [Key] attribute
foreach (var entity in modelBuilder.Model.GetEntityTypes()
    .Where(t => 
        t.ClrType.GetProperties()
            .Count(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute))) > 1))
{
    // get the keys in the appropriate order
    var orderedKeys = entity.ClrType
        .GetProperties()
        .Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)))
        .OrderBy(p => 
            p.CustomAttributes.Single(x => x.AttributeType == typeof(ColumnAttribute))?
                .NamedArguments?.Single(y => y.MemberName == nameof(ColumnAttribute.Order))
                .TypedValue.Value ?? 0)
        .Select(x => x.Name)
        .ToArray();

    // apply the keys to the model builder
    modelBuilder.Entity(entity.ClrType).HasKey(orderedKeys);
}

모든 상황에서 이것을 완전히 테스트하지는 않았지만 기본 테스트에서 작동합니다. 이것이 누군가에게 도움이되기를 바랍니다.

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