2010-01-20 9 views
7

मुझे लगता है कि संस्थाओं डिफ़ॉल्ट के रूप में प्राथमिक कुंजी तुलना द्वारा समानता को लागू करना चाहिए, लेकिन nhibernate प्रलेखन व्यापार पहचान का उपयोग की सिफारिश की: पहचानकर्ता मूल्य की तुलना द्वाराnhibernate: समानता को लागू करने के लिए सर्वोत्तम प्रथाएं क्या हैं?

सबसे स्पष्ट रास्ता बराबर लागू करने के लिए है()/GetHashCode() दोनों वस्तुओं के। यदि मान समान है, तो दोनों एक ही डेटाबेस पंक्ति होनी चाहिए, इसलिए वे बराबर हैं (यदि दोनों को आईसेट में जोड़ा जाता है, तो हमारे पास केवल आईएसईटी में एक तत्व होगा)। दुर्भाग्यवश, हम उस दृष्टिकोण का उपयोग नहीं कर सकते हैं। NHibernate केवल उन वस्तुओं को पहचानकर्ता मान निर्दिष्ट करेगा जो लगातार हैं, एक नव निर्मित उदाहरण में कोई पहचानकर्ता मूल्य नहीं होगा! हम व्यापार कुंजी समानता का उपयोग कर बराबर() और 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 के साथ जोड़ते है के रूप में ही है । तुलनात्मक मानों के रूप में डेटाबेस प्राथमिक कुंजी का उपयोग न करने का कारण यह है क्योंकि यह क्लाइंट साइड (पूर्व वृद्धिशील के लिए) पर प्राथमिक कुंजी उत्पन्न नहीं होने पर ऑब्जेक्ट के हैशकोड को बदल देगा और आप किसी प्रकार के हैशटेबल संग्रह (जैसे आईसेट) का उपयोग करते हैं। अपनी संस्थाओं को संग्रहित करने के लिए।

मैं एक समान समानता कार्यान्वयन कैसे बना सकता हूं जो समानता/हैशकोड (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx) के सामान्य नियमों को तोड़ता नहीं है और न ही निषेध नियमों के अनुरूप है?

+0

आप (विशेष रूप से) बराबर का उपयोग क्यों करना चाहते हैं? – apollodude217

उत्तर

13

यह ओआरएम के साथ एक ज्ञात मुद्दा है। यहां मैं उन समाधानों की रूपरेखा तैयार करता हूं जिन्हें मैं जानता हूं और कुछ पॉइंटर्स देता हूं।

1 सरोगेट/प्राथमिक कुंजी: स्वत: जनरेट

आप mentionned रूप में, यदि वस्तु सहेजा नहीं गया है, यह काम नहीं करता।

2 सरोगेट/प्राथमिक कुंजी: निर्दिष्ट किए गए मान

आप कोड में, इस तरह से वस्तु हमेशा एक आईडी है और तुलना के लिए इस्तेमाल किया जा सकता पी के मान देना तय कर सकते हैं। Don't let hibernate steal your identity देखें।

3 प्राकृतिक कुंजी

वस्तु किसी अन्य प्राकृतिक कुंजी, प्राथमिक कुंजी के अलावा अन्य है, तो आप इस एक का उपयोग कर सकते हैं। यह क्लाइंट इकाई के लिए मामला होगा, जिसमें एक संख्यात्मक प्राथमिक कुंजी और एक स्ट्रिंग क्लाइंट नंबर है। ग्राहक संख्या वास्तविक दुनिया में ग्राहक की पहचान करती है और एक प्राकृतिक कुंजी है जो नहीं बदलेगी।

4 वस्तु

महत्व देता समानता के लिए वस्तु मानों का उपयोग करना संभव है। लेकिन आपने अन्य कमियों का उल्लेख किया है। मानों में बदलाव होने पर यह समस्याग्रस्त हो सकती है और ऑब्जेक्ट संग्रह में है।उदाहरण के लिए, यदि आपके पास Set दो ऑब्जेक्ट्स हैं जो पहले अलग थे, लेकिन फिर आप सेट में संदर्भ के दौरान मान बदलते हैं ताकि वे बराबर हो जाएं। फिर आप Set का अनुबंध तोड़ते हैं। Hibernate equals and hashcode देखें।

5 मिश्रित: मूल्य + autogenerate प्राथमिक/किराए की कुंजी

वस्तुओं की तुलना करने के लिए तो एक आईडी पहले से ही है, इसका इस्तेमाल। अन्यथा, तुलना के लिए ऑब्जेक्ट मानों का उपयोग करें।

सभी के पास कुछ पेशेवर और विपक्ष हैं। आईएमएचओ, सबसे अच्छा 3 है, यदि यह आपके डोमेन मॉडल के साथ संभव है। अन्यथा, मैंने 5 का उपयोग किया है और यह काम करता है, हालांकि संग्रह का उपयोग करते समय अभी भी कुछ जाल हैं। मैंने कभी भी 2 का उपयोग नहीं किया है, लेकिन अगर आपको कोड में पीके उत्पन्न करने का कोई तरीका मिलता है तो यह एक समझदार समाधान भी लगता है। शायद अन्य लोगों के लिए पॉइंटर्स हैं।

+0

मुझे एक समस्या के रूप में ऑप्ट 1 नहीं दिखाई देता है यदि आप उन्हें रखने से पहले अपनी संस्थाओं को हश नहीं करते हैं (पूर्व में, आईसेट संग्रह का उपयोग न करें)। – Marius

+0

अच्छा एक (+1) बधाई –

संबंधित मुद्दे

 संबंधित मुद्दे