2010-01-20 27 views
7

Ben Varlıkları varsayılan olarak birincil anahtar kıyasla eşitliği hayata geçirmesi gerektiğini düşünüyorum, ama nhibernate dokümantasyon iş kimliğini kullanarak önerir: tanımlayıcı değeri karşılaştıraraknhibernate: eşitliği uygulamak için en iyi yöntemler nelerdir?

en açık yolu (Eşittir uygulamaktır)/GetHashCode() her iki nesnenin Değer aynı ise, her ikisi de aynı veritabanı satırı olmalıdır, dolayısıyla eşittirler (her ikisi de bir ISet'e eklenirse, yalnızca ISet'te bir öğeye sahip oluruz). Maalesef bu yaklaşımı kullanamıyoruz. NHibernate sadece tanımlayıcı değerleri kalıcı olan nesnelere atayacak, yeni oluşturulan bir örnek herhangi bir tanımlayıcı değere sahip olmayacaktır! İş anahtarı eşitliğini kullanarak Equals() ve GetHashCode() uygulamasını öneririz.

İş anahtar eşitlik demek ki Eşittir() yöntemi iş anahtarını, gerçek dünyada bizim örneğini tespit edecek bir tuşa (doğal aday anahtar)

Ve örneğini oluşturan sadece özelliklerini karşılaştırır (ayrıca dokümandan):

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

Bu iş kimlik kavramı (örneğin göre) nedeniyle iplik kafam ValueObjects ile ilişkilendirmek semantik türü temelde sözdizimi ile karşılaştırıldığında, aynı got . Veritabanı birincil anahtarlarını karşılaştırma değerleri olarak kullanmamanın nedeni, birincil anahtarın istemci tarafında üretilmemesi (eskiden artımlı olarak) ve bu tür bir hashtable koleksiyonunun (örneğin, ISet gibi) kullanılması durumunda nesnenin karma kodunu değiştireceğidir. varlıklarınızı depolamak için.

Eşitlik/hashcode (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) için genel kuralları ihlal etmeyen ve nhibernate kurallarına uymayan iyi bir eşitlik uygulamasını nasıl oluşturabilirim?

+0

Neden (özellikle) Equals'ı kullanmak ister misiniz? – apollodude217

cevap

13

Bu, ORM ile bilinen bir sorundur. Burada bildiğim çözümleri özetledim ve birkaç işaretçi verdim.

1 Vekil/birincil anahtar: Nesne kaydedilmedi eğer otomatik oluşturulan sen mentionned

, bu işe yaramaz.

2 Vekil/birincil anahtar: Atanan Değerin, kodda nesne daima bir kimliği vardır ve karşılaştırma için kullanılabilir bu şekilde PK değer atamak için karar verebilir

. Bakınız Don't let hibernate steal your identity. Nesne birincil anahtar dışındaki başka doğal anahtarı varsa

3 Doğal anahtar

, bu birini kullanabilirsiniz. Bu, bir dize istemci numarası ve sayısal bir birincil anahtarı olan bir istemci varlığı için geçerli olacaktır. Müşteri numarası, müşteriyi gerçek dünyada tanımlar ve değişmeyecek olan doğal bir anahtardır.

4 Nesne mümkündür eşitlik nesne değerlerini kullanarak

değer verir. Ama bahsettiğiniz başka eksiklikler var. Değerler değişirse ve nesne koleksiyonu koleksiyonundaysa bu sorun olabilir.Örneğin, ilk başta farklı olan iki nesneye sahip bir Set varsa, ancak değerler eşitlendikçe kümede başvuru yaparken değerleri değiştirirsiniz. Sonra Set'un sözleşmesini bozarsınız. Bakınız Hibernate equals and hashcode.

5 Karışık: değer + AutoGenerate primer/vekil anahtarlar

nesnelerin zaten bir kimliğe sahip karşılaştırma, bunu kullanır. Aksi takdirde, karşılaştırma için nesne değerlerini kullanın.

Tüm bazı artıları ve eksileri var. IMHO, alan modeliniz ile mümkün ise en iyisi 3'tür. Aksi halde 5 tane kullandım ve işe yaradı, ancak koleksiyonları kullanırken hala bir tuzak var. Hiç 2 kullanmadım ama bu kodda PK'yi oluşturmanın bir yolunu bulursanız da mantıklı bir çözüm gibi geliyor. Belki başkalarının bunun için işaretçiler vardır.

+0

Varlığınızı kullanmaya devam etmeden önce varlıklarınızı karmaşayamazsanız, opt 1'i sorun olarak görmüyorum (örneğin, ISet koleksiyonlarını kullanmayın). – Marius

+0

Güzel bir (+1) Tebrikler –

İlgili konular