새로운 프로젝트를 시작하고 POCO를 디자인 할 때마다 나 자신과 정신적 인 토론을합니다. 외래 키 연결 을 선호하는 것으로 보이는 많은 자습서 / 코드 샘플을 보았습니다 .
외래 키 연결
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; } // <-- Customer ID
...
}
독립적 인 협회와는 반대로 :
독립 협회
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
나는 과거에 NHibernate와 함께 일했고, 더 많은 OO를 느낄뿐만 아니라 (지연 로딩과 함께) 자신의 ID가 아닌 전체 Customer 객체에 대한 액세스를 제공하는 이점이있는 독립적 인 연결을 사용했습니다. 이를 통해 예를 들어 Order 인스턴스를 검색 한 다음 Order.Customer.FirstName
명시 적으로 조인 하지 않고도 수행 할 수 있습니다. 이는 매우 편리합니다.
요약하자면 내 질문은 다음과 같습니다.
- 독립적 인 연결을 사용하는 데 큰 단점이 있습니까? 과…
- 없는 경우 외래 키 연결을 사용하는 이유는 무엇입니까?
답변
ORM을 최대한 활용하려면 엔티티 참조를 사용해야합니다.
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
FK가있는 데이터베이스에서 엔티티 모델을 생성하면 항상 엔티티 참조가 생성됩니다. 이를 사용하지 않으려면 EDMX 파일을 수동으로 수정하고 FK를 나타내는 속성을 추가해야합니다. 적어도 이것은 독립 연결 만 허용 된 Entity Framework v1의 경우였습니다.
Entity Framework v4는 외래 키 연결이라는 새로운 유형의 연결을 제공합니다. 독립 키와 외래 키 연결의 가장 분명한 차이점은 Order 클래스입니다.
public class Order
{
public int ID { get; set; }
public int CustomerId { get; set; } // <-- Customer ID
public Customer Customer { get; set; } // <-- Customer object
...
}
보시다시피 FK 속성과 엔티티 참조가 모두 있습니다. 두 가지 유형의 연결 간에는 더 많은 차이점이 있습니다.
독립 협회
- 에서 별도의 개체로 표시됩니다
ObjectStateManager
. 그것은 자체가 있습니다EntityState
! - 연합을 구축 할 때 항상 연합의 양쪽 끝에서 엔티티가 필요합니다.
- 이 연관은 엔티티와 동일한 방식으로 매핑됩니다.
외래 키 연결
- 에서 별도의 개체로 표시되지 않습니다
ObjectStateManager
. 따라서 몇 가지 특별한 규칙을 따라야합니다. - 협회를 구축 할 때 양쪽 끝이 필요하지 않습니다. 하위 항목과 상위 항목의 PK가 있으면 충분하지만 PK 값은 고유해야합니다. 따라서 외래 키 연결을 사용할 때 관계에 사용되는 새로 생성 된 엔터티에도 임시 고유 ID를 할당해야합니다.
- 이 연관은 맵핑되지 않고 대신 참조 제한 조건을 정의합니다.
외래 키 연결을 사용하려면 엔터티 데이터 모델 마법사 의 모델 에 외래 키 열 포함 을 선택해야합니다 .
편집하다:
이 두 유형의 연관성 간의 차이점은 잘 알려져 있지 않아 이에 대한 자세한 내용과 내 의견을 담은 짧은 기사 를 작성했습니다 .
답변
둘 다 사용하십시오. 엔터티 참조를 가상으로 만들어 지연로드를 허용합니다. 이렇게 :
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; } // <-- Customer object
...
}
이를 통해 불필요한 DB 조회를 줄이고 지연 로딩을 허용하며 원하는 ID를 알고 있으면 쉽게 확인 / 설정할 수 있습니다. 둘 다 사용한다고해서 테이블 구조가 변경되는 것은 아닙니다.
답변
독립적 인 연관 AddOrUpdate
은 일반적으로 Seed
방법 에서 사용되는 것과 잘 작동하지 않습니다 . 참조가 기존 항목 인 경우 다시 삽입됩니다.
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);
그 결과 기존 고객이 다시 삽입되고 새 (다시 삽입 된) 고객이 새 주문과 연결됩니다.
외래 키 연결을 사용하고 ID를 할당하지 않는 한.
// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);
// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);
우리는 예상되는 동작을 가지고 있으며 기존 고객은 새로운 주문과 연결됩니다.
답변
불필요한 조회를 피하기 위해 객체 접근 방식을 선호합니다. 속성 객체는 팩토리 메서드를 호출하여 전체 항목을 빌드 할 때처럼 쉽게 채울 수 있습니다 (중첩 된 항목에 대한 간단한 콜백 코드 사용). 메모리 사용량을 제외하고는 볼 수있는 단점이 없습니다 (하지만 개체를 캐시 할 수 있습니까?). 따라서 수행중인 모든 작업은 스택을 힙으로 대체하고 조회를 수행하지 않아 성능을 향상시키는 것입니다. 이해가 되길 바랍니다.