2011-08-15 2 views
3

사이에 링크 (조인) 테이블이있을 때 두 테이블간에 일대 다 관계에 대한 질문이 있습니다.Entity Framework 코드 첫 번째 일대 다 관계 매핑 (링크 테이블 포함)

예 테이블 :

ChildTable: 
ID int NOT NULL PK 
Relation int NOT NULL 

ParentTable: 
ID int NOT NULL PK 
Name nvarchar(50) NOT NULL 

ParentChildren: 
ParentTable_ID int NOT NULL PFK 
ChildTable_ID int NOT NULL PFK 

엔티티 :

public class ChildTable 
{ 
    public ChildTable() 
    { 
     this.ParentTables = new List<ParentTable>(); 
    } 

    public int ID { get; set; }  
    public int Relation { get; set; } 
    public virtual ICollection<ParentTable> ParentTables { get; set; } 
} 

public class ParentTable 
{ 
    public ParentTable() 
    { 
     this.ChildTables = new List<ChildTable>(); 
    } 

    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<ChildTable> ChildTables { get; set; } 
} 

매핑 :

public class ChildTableMap : EntityTypeConfiguration<ChildTable> 
{ 
    public ChildTableMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.ID); 

     // Properties 
     // Table & Column Mappings 
     this.ToTable("ChildTable"); 
     this.Property(t => t.ID).HasColumnName("ID"); 
     this.Property(t => t.Relation).HasColumnName("Relation"); 
    } 
} 
public class ParentTableMap : EntityTypeConfiguration<ParentTable> 
{ 
    public ParentTableMap() 
    { 
     // Primary Key 
     this.HasKey(t => t.ID); 

     // Properties 
     this.Property(t => t.Name) 
      .IsRequired() 
      .HasMaxLength(50); 

     // Table & Column Mappings 
     this.ToTable("ParentTable"); 
     this.Property(t => t.ID).HasColumnName("ID"); 
     this.Property(t => t.Name).HasColumnName("Name"); 

     // Relationships 
     this.HasMany(t => t.ChildTables) 
      .WithMany(t => t.ParentTables) 
      .Map(m => 
       { 
        m.ToTable("ParentChildren"); 
        m.MapLeftKey("ParentTable_ID"); 
        m.MapRightKey("ChildTable_ID"); 
       }); 

    } 
} 

컨텍스트 :

public class TestContext : DbContext 
{ 
    static TestContext() 
    { 
     Database.SetInitializer<TestContext>(null); 
    } 

    public DbSet<ChildTable> ChildTables { get; set; } 
    public DbSet<ParentTable> ParentTables { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<IncludeMetadataConvention>(); 
     modelBuilder.Configurations.Add(new ChildTableMap()); 
     modelBuilder.Configurations.Add(new ParentTableMap()); 
    } 
} 

코드는 아동과 부모 추가 :

using (var context = new TestContext()) 
     { 
       var parent = new ParentTable { Name = "Mother Goose" };     
       var child = new ChildTable { Relation = 1 };     
       context.ParentTables.Add(parent); 
       context.ChildTables.Add(child); 
       parent.ChildTables.Add(child); 
       context.SaveChanges(); 
     } 

예상대로 모든 일을,하지만 난 정말 단 한 부모와 많은 아이들이있다.

링크 테이블 (ParentTable의 ICollection이없는 ChildTable 클래스가 변경된)에 쓰기를 포함하는 매핑을 수행하는 방법은 무엇입니까?

+0

기존 테이블 구조가 있고 변경할 수 있습니까? 일대 다 관계의 경우 일반적으로 조인 테이블을 삭제하고 ChildTable에 FK 열을 도입 할 수 있기 때문에 궁금합니다. 웬일인지 당신 테이블을 바꿀 수 없다고 생각해? – Slauma

+0

예, 링크 테이블이 없으면 매우 쉽지만, 불행히도이 링크 테이블은 변경할 수 없습니다. – Minnie

답변

7

그런 매핑을 정의 할 수 없습니다. 조인 테이블은 다 대다 관계에 대해서만 있습니다. 질문에 대한 주석에서 말한 것처럼 변경할 수없는 데이터베이스 스키마는 이미 다 대다 관계를 정의하고 있음을 명심해야합니다. 예를 들어이 두 항목 ...

ParentTable_ID: 1 2 
ChildTable_ID: 1 1 

...을 ParentChildren 테이블에 유효한 항목은, 그들은 PK 제약 조건을 위반하지 않는 그들은 자녀 1 두 부모 1, 2

을 가지고 있다고

비즈니스 로직에서 자식이 단 하나의 상위 항목 만 가질 수 있도록 허용하는 경우 데이터베이스 스키마가 잘못 모델링됩니다. 이 결함은 EF로 해결할 수 없습니다.

public class ChildTable 
{ 
    public ChildTable() 
    { 
     this.ParentTables = new List<ParentTable>(); 
    } 

    public int ID { get; set; }  
    public int Relation { get; set; } 
    public virtual ICollection<ParentTable> ParentTables { get; set; } 

    [NotMapped] // or use .Ignore(c => c.ParentTable) in Fluent API 
    public ParentTable ParentTable 
    { 
     get 
     { 
      return ParentTables.SingleOrDefault(); 
      // let is crash if there is more than one element in the list 
     } 

     set 
     { 
      var oldParent = ParentTables.SingleOrDefault(); 
      if (oldParent != value) 
      { 
       ParentTables.Clear(); 
       if (value != null) 
        ParentTables.Add(value); 
      } 
     } 
    } 
} 

그것은이다 :

가능한 해결 방법은 ChildTable 엔티티의 ParentTables 컬렉션 결코 아마하지 매핑 도우미 속성을 도입하여, 두 개 이상의 요소가없는 코드에서 비즈니스 로직을 보장하기 위해 수 있습니다 ParentTable 속성 만 사용하면 약간의 도움이됩니다. 컬렉션을 사용하고 하나 이상의 부모를 추가하는 것을 피해야합니다. 매핑해야하므로 private으로 만들 수 없습니다. 또한 관계의 다른 측면에서도 안전하지 않습니다. 다음과 같이 쓸 수 있습니다 : parent1.ChildTables.Add(child1); parent2.ChildTables.Add(child1); 그러면 데이터베이스에 child1이라는 두 명의 부모가 생깁니다. 추가 된 자식이 부모가 이미 this 부모가 아닌지 확인하는 자식을 ParentTable 엔티티에 추가하는 도우미 메서드를 작성하여이를 파악할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 죄송합니다. 답변에 투표 해 드릴 수 없습니다. 충분한 점수가 없습니다. – Minnie

관련 문제