2010-01-20 25 views
7

myślę, że podmioty powinny wdrożyć równości poprzez klucz podstawowy porównania jako domyślne, ale dokumentacja NHibernate zaleca stosowanie tożsamość działalności:nhibernate: jakie są najlepsze praktyki w zakresie wdrażania równości?

Najbardziej oczywistym sposobem jest wdrożenie equals()/GetHashCode() poprzez porównanie wartości identyfikatora obu obiektów. Jeśli wartość jest taka sama, oba muszą być tymi samymi wierszami bazy danych, dlatego są równe (jeśli oba zostaną dodane do ISet, będziemy mieli tylko jeden element w ISet). Niestety nie możemy użyć tego podejścia. NHibernate przydzieli tylko wartości identyfikatorów obiektom, które są trwałe, nowo utworzona instancja nie będzie miała żadnej wartości identyfikatora! Zalecamy stosowanie metod Equals() i GetHashCode() przy użyciu równości klucza biznesowego.

działalności równość klucz oznacza, że ​​equals() metoda porównuje tylko te właściwości, które stanowią klucz biznesowe, klucz, który będzie identyfikować nasze wystąpienie w realnym świecie (naturalny klucz potencjalny)

i przykład (również z doc):

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; 
} 

Ten dostał moja głowa wiruje, ponieważ pojęcie tożsamości gospodarczej (zgodnie z przykładem) jest taka sama jak porównanie za pomocą składni, która jest w zasadzie taki rodzaj semantyki kojarzy mi się z ValueObjects . Powodem nieużywania kluczy podstawowych bazy danych jako wartości porównawczych jest to, że spowoduje to zmianę kodu skrótu obiektu, jeśli klucz podstawowy nie zostanie wygenerowany po stronie klienta (na przykład przyrostowo) i użyjesz pewnego rodzaju zbioru haseł (takiego jak ISet) do przechowywania twoich bytów.

Jak mogę stworzyć dobrą realizację równości, które nie łamie ogólne zasady równości/hashcode (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) i zgodny z NHibernate zasad, jak również?

+0

Dlaczego (konkretnie) chcesz/potrzebujesz używać równań? – apollodude217

Odpowiedz

13

Jest to znany problem z ORM. Tutaj przedstawiam rozwiązania, o których wiem, i podam kilka wskazówek.

1 zastępczy/klucz podstawowy: auto generowane

Jak wymieniono, jeśli obiekt nie został zapisany, to nie działa.

2 zastępczy/klucz podstawowy: przypisana wartość

Możesz zdecydować przypisać wartość PK w kodzie, w ten sposób obiekt ma zawsze identyfikator i może być używany do porównania. Zobacz Don't let hibernate steal your identity.

3 Natural klucz

Jeśli obiekt ma inny klucz naturalny, inny niż klucz podstawowy, można użyć tego. Tak będzie w przypadku jednostki klienta, która ma numeryczny klucz podstawowy i numer klienta ciągu. Numer klienta identyfikuje klienta w świecie rzeczywistym i jest naturalnym kluczem, który nie ulegnie zmianie.

4 obiektu wartości

Wykorzystując wartości obiektu równości jest możliwy. Ale czy wspomniałeś o innych niedociągnięciach? Może to być problematyczne, jeśli wartości ulegną zmianie, a obiekt znajduje się w kolekcji kolekcji.Na przykład, jeśli masz Set z dwoma obiektami, które były różne na początku, ale potem zmieniasz wartości, gdy są one odniesieniem w zestawie, aby stały się równe. Potem łamiesz umowę z Set. Zobacz Hibernate equals and hashcode.

5 Mieszane: wartość + AutoGenerate pierwotne/klawisze zastępcze

Jeśli obiekty porównać mają już identyfikator, użyj go. W przeciwnym razie użyj wartości obiektów do porównania.

Wszystkie mają pewne zalety i wady. IMHO, najlepsze jest 3, jeśli jest to możliwe z twoim modelem domeny. W przeciwnym razie użyłem 5 i zadziałało, chociaż wciąż jest jakaś pułapka przy korzystaniu z kolekcji. Nigdy nie używałem 2, ale brzmi to również rozsądnie, jeśli znajdziesz sposób na wygenerowanie PK w kodzie. Może inni ludzie mają wskazówki na ten temat.

+0

Nie widzę opcji 1 jako problemu, jeśli nie mieszasz swoich jednostek przed ich utrwaleniem (np. Nie korzystaj z kolekcji ISet). – Marius

+0

Przyjemny (+1) Gratulacje –

Powiązane problemy