2010-01-20 1 views
7

나는 엔티티는 기본적으로 기본 키 비교하여 평등을 구현해야한다고 생각하지만, NHibernate에 문서 비즈니스 정체성을 사용하는 것이 좋습니다 : 식별자 값을 비교하여nhibernate : 평등을 구현하는 가장 좋은 방법은 무엇입니까?

가장 확실한 방법은 (같음을 구현하는 것입니다)/GetHashCode() 두 개체의 값이 같으면 둘 다 동일한 데이터베이스 행이어야하므로 동일합니다 (둘 다 ISet에 추가되면 ISet에 하나의 요소 만 포함). 불행히도, 우리는 그 접근법을 사용할 수 없습니다. Hibernate는 영속 객체들에 대해서만 식별자 값을 할당 할 것이고 새로 생성 된 인스턴스는 어떠한 식별자 값도 가지지 않을 것이다! 비즈니스 키 평등을 사용하여 Equals() 및 GetHashCode()를 구현하는 것이 좋습니다.

비즈니스 키 평등을 의미 같음() 메소드가 비지니스 키, 현실 세계에서 우리의 인스턴스를 식별하게 될 키 (천연 후보 키)

그리고 예를 형성하는 프로퍼티들만을 비교 (또한 문서에서) :

public override bool Equals(object other) 
{ 
    if (this == other) return true; 

    Cat cat = other as Cat; 
    if (cat == null) return false; // null or not a cat 

    if (Name != cat.Name) return false; 
    if (!Birthday.Equals(cat.Birthday)) return false; 

    return true; 
} 

이 비즈니스 정체성의 개념은 (예에 따라) 때문에 회전 내 머리는 내가 ValueObjects와 연관 의미의 유형은 기본적으로 문법으로 비교와 동일합니다 있어요 . 데이터베이스 기본 키를 비교 값으로 사용하지 않는 이유는 기본 키가 클라이언트 측에서 생성되지 않고 (예 : 증분) 사용자가 일종의 해시 테이블 콜렉션 (예 : ISet)을 사용하면 객체의 해시 코드가 변경되기 때문입니다. 엔티티 저장 용.

내가 평등/해시 코드 (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx)에 대한 일반적인 규칙을 깰뿐만 아니라 NHibernate에 규칙을 준수하지 않는 좋은 평등 구현을 만들 수있는 방법 ?

+0

왜 Equals를 사용하고 싶습니까? – apollodude217

답변

13

이것은 ORM의 알려진 문제입니다. 여기서 내가 아는 해결책을 설명하고 몇 가지 지침을 제공합니다.

1 대리/기본 키 : 오브젝트가 저장되지 않은 경우 자동으로 생성하면 했나요으로

을,이 작동하지 않습니다.

2 대리/기본 키 : 할당 된 값 당신은 코드에서 객체가 항상 ID를 가지고 비교를 위해 사용할 수있는이 방법을 PK의 값을 할당하도록 결정할 수 있습니다

. Don't let hibernate steal your identity을 참조하십시오. 객체가 기본 키가 아닌 다른 자연 키가있는 경우,

3 자연 키

, 당신이 하나를 사용할 수 있습니다. 숫자 기본 키 문자열 클라이언트 번호가있는 클라이언트 엔터티의 경우입니다. 클라이언트 번호는 실제 세계에서 클라이언트를 식별하며 변경되지 않는 자연스러운 키입니다.

4 개체 가능 어떤지 개체 값을 사용

값. 그러나 당신이 언급 한 다른 단점이 있습니다. 값이 변경되고 개체가 컬렉션에 있으면 문제가 될 수 있습니다.예를 들어, 처음에 다른 두 개의 개체가있는 Set이 있지만 그 값이 같아 지도록 집합에서 참조 인 동안 값을 변경하면됩니다. 그런 다음 Set 계약을 파기합니다. Hibernate equals and hashcode을 참조하십시오.

혼합 5 : 자동 생성 기본 값 +/대리 키

개체가 이미 ID를 비교하는 경우, 사용. 그렇지 않으면, 비교를 위해 오브젝트 값을 사용하십시오.

모두 장단점이 있습니다. IMHO, 귀하의 도메인 모델에서 가능하다면 최고 3 점입니다. 그렇지 않으면 컬렉션을 사용할 때 여전히 함정이 있지만 5를 사용했고 효과가있었습니다. 나는 2를 사용하지는 않았지만 코드에서 PK를 생성 할 수있는 방법을 찾으면 그것은 합리적인 해결책으로 들린다. 어쩌면 다른 사람들도이 점에 대한 지침을 가지고있을 것입니다.

+0

내가 그들을 유지하기 전에 엔티티를 해시하지 않으면 (예 : ISet 콜렉션을 사용하지 마십시오) 문제 1을 선택하지 마십시오. – Marius

+0

좋은 +1 (+1) 축하합니다. –