수색…


소개

이 항목에서는 Entity Framework Code First를 사용하여 일대 다 및 다 대다 관계를 매핑하는 방법에 대해 설명합니다.

일대 다 매핑

그래서 여러분이 다음과 같은 두 개의 엔티티를 가지고 있다고 가정 해 봅시다.

public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
}

public class MyDemoContext : DbContext
{
   public DbSet<Person> People { get; set; }
   public DbSet<Car> Cars { get; set; }
}

그리고 그들 사이에 일대 다 관계를 설정하고자합니다. 즉, 한 사람이 0 대, 하나 이상의 자동차를 가질 수 있으며, 한 대의 자동차가 정확히 한 사람에게 속합니다. 모든 관계는 양방향이므로 사람이 차를 가지고 있으면 차가 그 사람의 것이됩니다.

이렇게하려면 모델 클래스를 수정하면됩니다.

public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Car> Cars { get; set; } // don't forget to initialize (use HashSet)
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
   public int PersonId { get; set; }
   public virtual Person Person { get; set; }
}

그리고 그것은 :) 당신은 이미 당신의 관계를 설정했습니다. 데이터베이스에서 이것은 외래 키로 표현됩니다.

일대 다 매핑 : 대회와의 비교

마지막 예제에서, EF는 어떤 열이 외래 키인지를 가리키고 어디에서 가리켜 야 하는지를 알 수 있습니다. 방법? 규칙을 사용하여. 형의 속성 갖는 Person 이라는 PersonPersonId 특성은 결론에 EF 리드 PersonId 외부 키이며, 유형에 의해 표현되는 테이블의 기본 키를 가리키는 Person .

그러나 자동차 유형에서 PersonIdOwnerIdPerson to Owner 로 변경할 경우 어떻게됩니까?

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }
   public int OwnerId { get; set; }
   public virtual Person Owner { get; set; }
}

불행하게도이 경우 규칙은 올바른 DB 스키마를 생성하기에 충분하지 않습니다.

걱정 마; 당신은 모델에서 당신의 관계와 열쇠에 대한 힌트를 가지고 EF를 도울 수 있습니다. OwnerId 속성을 FK로 사용하도록 Car 유형을 구성하기 만하면됩니다. 엔티티 유형 구성을 작성하고 OnModelCreating() 에 적용하십시오.

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasRequired(c => c.Owner).WithMany(p => p.Cars).HasForeignKey(c => c.OwnerId);
  }
}

이것은 기본적으로 Car 에 필수 속성 인 Owner ( HasRequired () )가 있고 Owner 유형에서 Cars 속성은 자동차 엔터티 ( WithMany () )를 다시 참조하는 데 사용됩니다. 마지막으로 외래 키를 나타내는 속성이 지정됩니다 ( HasForeignKey () ). 이렇게하면 우리가 원하는 스키마를 얻을 수 있습니다.

Person 측면에서도 관계를 구성 할 수 있습니다.

public class PersonEntityTypeConfiguration : EntityTypeConfiguration<Person>
{
  public PersonEntityTypeConfiguration()
  {
    this.HasMany(p => p.Cars).WithRequired(c => c.Owner).HasForeignKey(c => c.OwnerId);
  }
}

아이디어는 동일합니다. 단지 측면이 다릅니다 ( '이 사람은 많은 차량을 소유하고 있으며, 각 차량에는 필요한 소유자가 있습니다.'). Person 측면 또는 Car 측면에서 관계를 구성하는 경우 중요하지 않습니다. 두 가지를 모두 포함 할 수도 있지만,이 경우 양쪽에서 동일한 관계를 지정하는 데주의하십시오!

0 또는 일대 다 매핑

앞의 예에서 자동차는 사람 없이는 존재할 수 없습니다. 그 사람을 자동차 쪽에서 선택 사항으로 원한다면 어떨까요? 글쎄, 그것은 일종 다수를하는 방법을 아는 것, 일종의 쉽습니다. CarPersonId 를 nullable로 변경하십시오.

public class Car
{
    public int CarId { get; set; }
    public string LicensePlate { get; set; }
    public int? PersonId { get; set; }
    public virtual Person Person { get; set; }
}

그리고 다음 사용 HasOptional () (또는 WithOptional ()를 구성을 할 수있는 측면에서 따라) :

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
  public CarEntityTypeConfiguration()
  {
     this.HasOptional(c => c.Owner).WithMany(p => p.Cars).HasForeignKey(c => c.OwnerId);
  }
}

다 대다

모든 사람이 여러 대의 자동차를 소유 할 수 있고 모든 자동차가 여러 명의 소유자를 가질 수있는 다른 시나리오로 넘어 갑니 다 (단, 다시 양방향 관계입니다). 이것은 다 - 대 - 다 관계입니다. 가장 쉬운 방법은 EF가 규칙을 사용하여 마술을하도록하는 것입니다.

다음과 같이 모델을 변경하십시오.

 public class Person
{
   public int PersonId { get; set; }
   public string Name { get; set; }
   public virtual ICollection<Car> Cars { get; set; }
}

public class Car
{
   public int CarId { get; set; }
   public string LicensePlate { get; set; }        
   public virtual ICollection<Person> Owners { get; set; }
}

그리고 스키마 :

거의 완벽 해. 보시다시피, EF는 사람 - 자동차 페어링을 추적 할 수있는 조인 테이블의 필요성을 인식했습니다.

다 대다 : 조인 테이블 사용자 정의

조인 테이블의 필드 이름을 좀 더 친숙하게 변경할 수 있습니다. 일반적인 구성 방법을 사용하여이 작업을 수행 할 수 있습니다 (어느 쪽에서 구성을 수행하든 상관 없습니다).

public class CarEntityTypeConfiguration : EntityTypeConfiguration<Car>
{
   public CarEntityTypeConfiguration()
   {
      this.HasMany(c => c.Owners).WithMany(p => p.Cars)
          .Map(m =>
              {
                 m.MapLeftKey("OwnerId");
                 m.MapRightKey("CarId");
                 m.ToTable("PersonCars");
              }
        );
  }
}

이 자동차에는 많은 소유자 ( HasMany () )가 있으며, 각 소유자는 많은 자동차 ( WithMany () )를 가지고 있습니다. 당신이 OwnerId 왼쪽 키를 매핑 할 수 있도록이지도 ( MapLeftKey () ), CarId에 오른쪽 키 ( MapRightKey () 테이블 PersonCars에)와 모든 일 ( ToTable () ). 그리고 이것은 당신에게 정확하게 그 스키마를 제공합니다 :

다 대다 : 사용자 정의 조인 엔티티

나는 정말로 EF가 조인 엔티티를 사용하지 않고 조인 테이블을 유추하게하는 팬이 아니라는 것을 인정해야합니다. 테이블을 수정할 수 없으므로 사람 - 자동차 협회에 추가 정보를 추적 할 수 없습니다 (유효한 날짜를 말하십시오).

또한 조인 테이블의 CarId 는 기본 키의 일부이므로 가족이 새 차를 구입하는 경우 먼저 이전 연결을 삭제하고 새 연결을 추가해야합니다. EF는 여러분이 숨 깁니다, 그러나 이것은 당신이 (즉, 자주 삽입을 언급 / 삭제는 인덱스 조각화가 발생할 수 없습니다 - 좋은 일 대신 간단한 업데이트의 두 가지 작업을 수행해야 함을 의미 쉽게 수정이 그것에 대해).

이 경우 하나의 특정 차량과 특정 사람에 대한 참조가있는 조인 엔티티를 생성 할 수 있습니다. 기본적으로 다 대 다 연관은 두 개의 일대 다 연관의 조합으로 보입니다.

public class PersonToCar
{
   public int PersonToCarId { get; set; }
   public int CarId { get; set; }
   public virtual Car Car { get; set; }
   public int PersonId { get; set; }
   public virtual Person Person { get; set; }
   public DateTime ValidFrom { get; set; }
}

public class Person
{
  public int PersonId { get; set; }
  public string Name { get; set; }
  public virtual ICollection<PersonToCar> CarOwnerShips { get; set; }
}

public class Car
{
  public int CarId { get; set; }
  public string LicensePlate { get; set; }        
  public virtual ICollection<PersonToCar> Ownerships { get; set; }
}

public class MyDemoContext : DbContext
{
  public DbSet<Person> People { get; set; }
  public DbSet<Car> Cars { get; set; }
  public DbSet<PersonToCar> PersonToCars { get; set; }
}

이것은 훨씬 더 많은 컨트롤을 제공하고 훨씬 더 유연합니다. 이제 사용자 지정 데이터를 연결에 추가 할 수 있으며 모든 연결에는 자체 기본 키가 있으므로 차 또는 소유자 참조를 업데이트 할 수 있습니다.

이 것은 실제로 두 개의 일대 다 관계의 조합 일 뿐이므로 앞의 예제에서 설명한 모든 구성 옵션을 사용할 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow