2009-05-13 8 views
16

डोमेन इकाइयों में आईडी फ़ील्ड रखना ठीक क्यों माना जाता है? मैंने कई समाधान देखा है जो आईडी और आईडी-आधारित GetHashCode/Equals के साथ बेस क्लास प्रदान करते हैं।डीडीडी: प्राथमिक कुंजी (आईडी) और ओआरएम (उदाहरण के लिए, एनएचबीर्नेट)

डोमेन मॉडल की मेरी समझ यह है कि इसमें केवल डोमेन से संबंधित चीजें होनी चाहिए। जबकि दुर्लभ मामलों (ट्रैक करने योग्य आदेश) आईडी में सार्थक हैं, ज्यादातर समय वे डीबी/यूआई में ऑब्जेक्ट्स को संदर्भित करने के लिए एक आसान तरीका को छोड़कर कुछ भी प्रदान नहीं करते हैं।

मुझे इक्विल्स/गेटहाशकोड लाभ भी नहीं दिखते हैं, क्योंकि पहचान मानचित्र कार्यान्वयन की गारंटी होनी चाहिए कि संदर्भ समानता आईडी समानता है।

अजीब, मैं आसानी से अन्य लोगों को इस विषय पर क्या सोचते हैं नहीं मिल रहा है, तो मैं इसे यहाँ पूछ रहा हूँ। डोमेन इकाइयों में गैर-डोमेन संबंधित आईडी का उपयोग करने पर सामान्य राय क्या है? और क्या एनएचबीरनेट के साथ कोई समस्या है यदि मैं अपने डोमेन इकाइयों में आईडी नहीं जोड़ता हूं?

अद्यतन:

जवाब के लिए धन्यवाद।

उनमें से कई सुझाव है कि ईद होने ORM एक DB अद्यतन करने के लिए एक ही रास्ता है। मुझे नहीं लगता कि यह मामला है। ओआरएम पहले ही डीबी से लोड की गई सभी इकाइयों का ट्रैक रखता है, इसलिए जब इसे किसी की आवश्यकता होती है तो इसे आसानी से आईडी प्राप्त करने में सक्षम होना चाहिए।

अद्यतन 2: न्याय और समान अंक के

उत्तर: क्या हम एक वेब अनुप्रयोग और जरूरत सत्र के बीच इकाई को संदर्भित करने के लिए एक रास्ता है या नहीं? संपादन/संसाधन/आईडी की तरह?

ठीक है, मैं विवश यूआई/पर्यावरण का एक विशिष्ट जरूरत है, न कि एक डोमेन मॉडल की जरूरत के रूप में देखते। GetIdentitity विधि (लोड (पहचान) विधि के साथ संगत) के साथ एक एप्लिकेशन सेवा या भंडार होने के कारण इस परिदृश्य के लिए पर्याप्त लगता है।

+1

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

+0

जब मैं क्लाइंट से ऑब्जेक्ट प्राप्त करता हूं तो मैं इस तथ्य का जिक्र नहीं कर रहा हूं। इस मामले में मुझे शायद कुछ डीटीओ मिलते हैं जिसमें एक आईडी है (और यह प्रासंगिक है भले ही मेरे पास डीबी न हो और स्मृति में सब कुछ स्टोर न करें, इस मामले में डीटीओ में आईडी कुछ आंतरिक हैशटेबल में एक कुंजी हो सकती है)। लेकिन क्लाइंट को ऑब्जेक्ट भेजने से पहले, मैं एक आईडी प्राप्त कर सकता हूं और इसे भेज रहा हूं डीटीओ में जोड़ सकता हूं। या बस कुछ मामलों में एक आईडी भेजें। –

+0

मैंने एनएच दस्तावेज में पाया कि एनएच को आईडी संपत्ति की आवश्यकता नहीं है! मेरा जवाब देखें, मैंने एक सेक्शन जोड़ा। –

उत्तर

4

मैं सिर्फ NHibernate के बारे में बात कर सकते हैं के बारे में जानें। वहां आपको प्राथमिक कुंजी के लिए एक फ़ील्ड की आवश्यकता है, यदि आप व्यवसाय डेटा (अनुशंसित नहीं) या किसी व्यवसाय अर्थ के साथ सरोगेट कुंजी लेते हैं, तो यह आपके ऊपर निर्भर करता है।

ठेठ परिदृश्य हैं:

  • ऑटो बढ़ाने डेटाबेस
  • GUID NHibernate
  • द्वारा उत्पन्न
  • व्यापार तर्क

द्वारा उत्पन्न GUID द्वारा उत्पन्न मूल्य वहाँ एक बड़ा लाभ है एक अद्वितीय आईडी है। जब आप अपने ऑब्जेक्ट को पास करते हैं, उदाहरण के लिए क्लाइंट और सर्वर पर वापस, तो आप स्मृति पहचान पर भरोसा नहीं कर सकते हैं। आप एक ही व्यवसाय उदाहरण की याद में कई उदाहरण भी प्राप्त कर सकते हैं। व्यापार उदाहरण आईडी द्वारा पहचाना जाता है।

आईडी-आधारित तुलना स्वाद का विषय है। व्यक्तिगत रूप से मुझे सरल और विश्वसनीय कोड पसंद है, और आईडी-आधारित तुलना सरल और विश्वसनीय है, जबकि गहरी तुलना हमेशा थोड़ा जोखिम भरा, त्रुटि-प्रवण, अनजान है। तो आप ऑपरेटर == के साथ स्मृति पहचान की तुलना करते हैं और व्यापार (और डेटाबेस) पहचान की तुलना में बराबर होते हैं।

एनएचबेर्नेट एक क्लास मॉडल को मैप करने के लिए एक कमजोर तरीका है जो मुझे पता है। हमारी बड़ी परियोजना में हमारे पास प्राथमिक कुंजी और संस्करण गुण हैं (वे आशावादी लॉकिंग के लिए उपयोग किए जाते हैं)। आप तर्क दे सकते हैं कि यह घुसपैठ कर रहा है, क्योंकि इसका उपयोग व्यावसायिक तर्क के लिए नहीं किया जाता है।

एनएच को इन गुणों की आवश्यकता नहीं है। (हालांकि इसे प्राथमिक कुंजी के रूप में गुणों में से एक की आवश्यकता है।) लेकिन विचार करें:

  • यह बेहतर काम करता है, उदाहरण के लिए।निराशावादी लॉकिंग केवल उपयुक्त संपत्ति के साथ संभव है,
  • तेज़: int आईडी कई डेटाबेस पर बेहतर प्रदर्शन करता है तो अन्य डेटा प्रकार
  • और आसान: व्यवसाय के अर्थ के साथ गुण लेना कई कारणों से निराश होता है।

तो क्यों ज़रूरी ज़रूरी ज़रूरी ज़रूरी ज़रूरी है?


संपादित करें: बस the documentation पढ़ सकते हैं और पाया NHibernate नहीं लगातार कक्षा में एक आईडी संपत्ति की आवश्यकता है कि! यदि आपके पास इंडेंटिफायर नहीं है, you can't use some features। यह अनुशंसा की जाती है कि यह आपके जीवन को आसान बनाता है।

+1

क्लाइंट-सर्वर पासिंग एक विशिष्ट उपयोग केस है - यह एक पहचान प्रदाता या भंडार विधियों के द्वारा हल करने योग्य है जिनका उपयोग इस विशिष्ट मामले (GetId (ऑब्जेक्ट), GetById (आईडी) के लिए किया जाता है)। अगर हम ओआरएम का उपयोग करते हैं तो मुझे स्मृति पहचान और व्यावसायिक पहचान के बीच अंतर दिखाई नहीं देता है। जहां तक ​​मैं समझता हूं, एक सत्र के भीतर हमेशा एक आईडी के साथ एक ही वस्तु होगी (अनुमानों को छोड़कर, लेकिन इन्हें तुलना करने के लिए दिलचस्प नहीं है)। –

+2

मैं आपका मुद्दा देखता हूं कि व्यवसाय डेटा कुंजी की अनुशंसा क्यों नहीं की जाती है, लेकिन मेरा मूल प्रश्न सरोगेट कुंजी का उपयोग करने के बारे में है - लेकिन केवल डीबी में, जहां यह संबंधित है। इसलिए यदि एनएचबीर्नेट को सरोगेट डीबी कुंजी पता है तो नुकसान लागू नहीं होना चाहिए - मैं इसे अपने डोमेन इकाइयों में परिभाषित नहीं करना चाहता हूं। –

+0

आपका मतलब है: यदि आपके पास क्लाइंट-सर्वर एप्लिकेशन नहीं है, और कभी भी एक सत्र से दूसरे सत्र में ऑब्जेक्ट पास नहीं करना है (उदाहरण के लिए समय, नेटवर्क, फ़ाइल के साथ स्थानांतरण) और सरोगेट व्यवसाय की पहचान की आवश्यकता नहीं है, तो NHibernate डेटाबेस प्राथमिक कुंजी आंतरिक रूप से प्रबंधित करें। यह शायद सच है, लेकिन यह स्वाभाविक रूप से मजबूत सीमाओं के साथ एक बहुत ही दुर्लभ मामला होगा। आप एनएचबेर्नेट के जिरा में फीचर एन्हांसमेंट के रूप में इसका प्रस्ताव दे सकते हैं। या इसे एक पैच के रूप में लागू करें। –

0

आपको इसे एक या दूसरे तरीके से रखना होगा ताकि ओआरएम अपडेट करने के लिए डेटाबेस पर वापस जा सके; मुझे लगता है कि यह एक निजी वर्ग में निजी और छुपा हो सकता है लेकिन उस तरह के पीओसीओ अवधारणा का उल्लंघन करता है।

+0

पोस्ट अपडेट देखें, मुझे लगता है कि ओआरएम वैसे भी आईडी जानता है, यह सिर्फ पहचान मानचित्र का उपयोग रिवर्स में कर सकता है। –

+0

आप कह रहे हैं कि ओआरएम वर्तमान में सिस्टम में सभी ऑब्जेक्ट्स का ट्रैक रखता है? मैं एक तथ्य के लिए नहीं कह सकता लेकिन यह असंभव लगता है। –

+0

एक सत्र के भीतर, हाँ, यह चाहिए। कॉन्फ़िगरेशन के आधार पर, सत्र एक वेब अनुरोध या यहां तक ​​कि एक संपूर्ण धागा या एप्लिकेशन जीवनकाल हो सकता है। इसका कारण यह है कि जब आप SubmitChanges को कॉल करते हैं तो उसे पता होना चाहिए कि परिवर्तन क्या हैं। और AFAIK अधिकांश ओआरएम http://martinfowler.com/eaaCatalog/identityMap.html को लागू करते हैं, साथ ही इसका भी अर्थ है कि उन्हें यह जानना है कि उनके पास पहले से क्या है। –

0

यह सोचते हैं कि अपनी पहचान अपने प्राथमिक कुंजी है, तो आप किसी भी डेटा को बिना वापस डीबी को बचाने के लिए सक्षम नहीं होगा।
जहां तक ​​बराबर और GetHashCode जाते हैं, ये सूची में ऑर्डर करने के लिए हैं जहां आप एक कस्टम ऑर्डरिंग बनाते हैं।

जवाब के लिए धन्यवाद।

उनमें से कई सुझाव है कि ईद होने ORM एक DB अद्यतन करने के लिए एक ही रास्ता है। मुझे नहीं लगता कि यह मामला है। ओआरएम पहले ही डीबी से लोड की गई सभी इकाइयों का ट्रैक रखता है, इसलिए जब इसे किसी की आवश्यकता होती है तो इसे आसानी से आईडी प्राप्त करने में सक्षम होना चाहिए।

अगर ऐसा होता तो मुझे आश्चर्य होगा। आम तौर पर यह आपके द्वारा परिभाषित गुणों से केवल एक सम्मिलन कथन बनाता है।

+0

पोस्ट अपडेट देखें, मुझे लगता है कि ओआरएम आंतरिक रूप से आईडी जानता है। –

+0

अगर यह मामला था तो मुझे आश्चर्य होगा। आम तौर पर यह आपके द्वारा परिभाषित गुणों से केवल एक सम्मिलन कथन बनाता है। हां, क्योंकि ज्यादातर मामलों में यह समझ में आता है। हालांकि, एक अच्छा ओआरएम भी आपके ऑब्जेक्ट का पिछला संस्करण है और सामान्य रूप से आपकी ऑब्जेक्ट के बारे में जितनी चाहें उतनी जानकारी संग्रहीत कर सकता है। मैंने अभी एक उदाहरण दिया है कि डालने में अतिरिक्त डेटा कैसे जोड़ा जा सकता है: http://www.dav-evans.com/?p=75। –

0

पहचान के बिना एक ही वस्तु प्राप्त करने के लिए कोई अन्य विकल्प नहीं है।उदाहरण के लिए लोगों के पास सामाजिक सुरक्षा संख्या या व्यक्तिगत कोड या कुछ अद्वितीय है और हम उन्हें पहचान सकते हैं।

आप प्राकृतिक पहचान का उपयोग कर सकते हैं लेकिन यह त्रुटि प्रवण है।

बस आईडी पहचानने के लिए नाम बदलें। यह डोमेन मॉडल में अच्छा दिखता है।

इकाइयों को संस्थाएं कहा जाता है क्योंकि उनके पास पहचान है।

+0

वेब परिस्थितियों और अन्य समान मामलों के लिए, कुछ प्रकार की IIDentityService जो वास्तव में NHibernateIdentityService हो सकती है पर्याप्त होगी (लेकिन यह एक विशिष्ट मामला है जब आप भविष्य के पुनर्प्राप्ति के लिए कुछ विशिष्ट ऑब्जेक्ट को संदर्भित करना चाहते हैं, डोमेन मॉडल के लिए पर्याप्त सामान्य नहीं)। –

0

मैं आम तौर पर बेस एंटिटी क्लास के रूप में डोमेन में आईडी शामिल करता हूं। मुझे ओआरएम का उपयोग करने के किसी अन्य तरीके से नहीं पता।

विशिष्टता/समानता निर्धारित करने के लिए एक आईडी का उपयोग करके डोमेन में एक वस्तु पहले से ही अनूठी है, अभ्यास में वास्तव में अलग नहीं है। मुझे अब तक इस दृष्टिकोण के लिए गंभीर दुष्प्रभाव का सामना नहीं हुआ है।

-1

आप समग्र कुंजी नामक पहचान स्थापित करने के लिए कई फ़ील्ड का भी उपयोग कर सकते हैं। हालांकि, इसके अंत में आपको अधिक काम की आवश्यकता होगी।

उन्हें here

+0

क्या इसका मतलब यह है कि मुझे तालिका में वही प्राथमिक कुंजी रखना होगा? –

+0

खैर, हाँ, निब में पहचान डीबी में पहचान की आवश्यकता है .. यह बिंदु की तरह है .. –

1

एनएच में, आप अलग-अलग उदाहरणों के लिए संदर्भ समानता का उपयोग नहीं कर सकते हैं। यह आपको उन ग्राहकों में एनएच का उपयोग करने के लिए तैयार करता है जो इस व्यवहार का उपयोग करना चाहते हैं (मेरी राय में यह सही व्यवहार है, एनएच जादू पर निर्भर नहीं है!)।

वेब ऐप्स या सत्र आधारित उपयोगों में जहां आप एक आईएसओशन के दायरे में डीबी पर जा सकते हैं, मुझे लगता है कि मैं यह कहने में सही हूं कि आप संदर्भ समानता पर भरोसा कर सकते हैं। लेकिन एक स्मार्ट क्लाइंट परिदृश्य में, या अधिक विशेष रूप से, कोई भी परिदृश्य जिसमें दो आईएसएशन एक उदाहरण साझा कर रहे हैं (जिसे डीबी में लोड किया गया है या डाला गया है, फिर दूसरे को पास किया गया है), आपको डीबी आईडी फ़ील्ड (साथ) के साथ संग्रहीत करने की आवश्यकता है उदाहरण

नीचे दिए गए दूसरे सत्र को यह नहीं पता होगा कि यह उदाहरण पारित किया जा रहा है, इसे पहले से ही डाला जा चुका है और अपडेट की आवश्यकता है, और यहां तक ​​कि अगर आपने इसे अपडेट में बदल दिया है, तो मुझे लगता है कि मैं यह सोचने में सही हूं कि यह नहीं जा रहा है कक्षा की डीबी आईडी जानने के लिए।

class SomeEntityWithNoId 
{ 
public blah etc {} 
} 

class dao 
{ 

void DateMethod() 
{ 
var s1 = sessionFactory.OpenSession(); 
var instance = new SomeEntityWithNoId(); 
instance.Blah = "First time, you need to insert"; 
s1.Save(s1); //now instance is persisted, has a DB ID such as identity or Hilo or whatever 
s1.close(); 
var s2 = sessionFactory.OpenSession(); 
s2.Blah = "Now update, going to find that pretty hard as the 2nd session won't know what ID to use for the UPDATE statement"; 

s2.Update(instance); //results in boom! exception, the second session has no idea *how* to update this instance. 




} 
} 

आप ID फ़ील्ड (रों), जो आप सोच में सही कर रहे हैं के बारे में चिंतित हैं, तो हठ चिंताओं के अलावा और कुछ के लिए काफी हद तक बेकार है, तो आप उन्हें निजी बना सकते हैं, तो कम से कम इस व्यवहार और शब्दों को समाहित हैं । आप पाते हैं कि यह दृष्टिकोण टीडीडी में कुछ घर्षण डालता है।

मुझे लगता है कि आप कम से कम एनएच के संबंध में आईडी मानचित्र के बारे में सही हैं। यदि सत्र पहली बार सत्र से जुड़ा हुआ होता है, तो आपके प्रकार को किसी क्षेत्र में अपनी डीबी आईडी स्टोर करने की आवश्यकता नहीं होती है। मुझे लगता है कि सत्र डीबी के साथ अपने रिश्ते को प्रबंधित करने के बारे में जानेंगे। मुझे यकीन है कि आप इस व्यवहार को साबित करने के लिए एक परीक्षण निकाल सकते हैं; पी

+0

मैं आपकी पोस्ट से सहमत हूं, लेकिन मुझे लगता है कि प्रदान किए गए उदाहरण (एक ऑब्जेक्ट के साथ 2 बाद के सत्र) NHibernate के लिए एक सामान्य उपयोग केस नहीं है। सर्वर से क्लाइंट को ऑब्जेक्ट भेजना एक और कहानी है, लेकिन इस मामले में वे डीटीओ हो सकते हैं या एक कस्टम सीरिएलाइज़र है जो आईडी को भेजा/प्राप्त किया जा सकता है। –

3

आमतौर पर, आपके पास एक वास्तविक डोमेन मॉडल नहीं होगा। आपके पास असंख्य समवर्ती और अनुक्रमिक सत्र होंगे, जिन्हें समेकित किया जाना चाहिए, और जिनमें से प्रत्येक में इसके लघु, पृथक, लेनदेन संबंधी डोमेन मॉडल शामिल हैं। आपके पास दो समवर्ती या दो अनुक्रमिक सत्रों के बीच एक ही ऑब्जेक्ट उदाहरण नहीं होंगे। लेकिन आपको यह सुनिश्चित करने के लिए कुछ तरीके की आवश्यकता होगी कि आप एक सत्र से दूसरे सत्र में जानकारी ले जा सकें।

एक उदाहरण, निश्चित रूप से, एक/संसाधन/सूची और/संसाधन/शो/आईडी यूआरएल की जोड़ी है (एएसपीनेट एमवीसी में नियंत्रक क्रियाओं की उचित जोड़ी के अनुरूप)। एक से दूसरे में स्थानांतरित होने पर, दो पूरी तरह से स्वतंत्र सत्र होते हैं, लेकिन उन्हें एक दूसरे के साथ (HTTP और ब्राउज़र के माध्यम से) संवाद करने की आवश्यकता होती है।

डेटाबेस का उपयोग किए बिना भी, आपके डोमेन मॉडल ऑब्जेक्ट्स अभी भी को पहचान के कुछ रूप की आवश्यकता है क्योंकि आपके पास अभी भी कई लघु, पृथक डोमेन मॉडल होंगे, न कि एक वास्तविक डोमेन मॉडल; और आपके पास ये सभी डोमेन मॉडल स्वतंत्र सत्रों में एक ही समय में और एक के बाद दोनों होंगे।

ऑब्जेक्ट समानता पर्याप्त नहीं है, क्योंकि ऑब्जेक्ट्स सत्रों के बीच समान नहीं हैं, भले ही अंतर्निहित वैचारिक संस्थाएं वे समान इकाई हों।

+2

अच्छी तरह से वर्णित बिंदु के लिए धन्यवाद। पोस्ट अपडेट देखें 2. मैं सहमत हूं कि यदि आप/संसाधन/शो/आईडी करना चाहते हैं तो आपको एक क्रमिक संदर्भ/पहचान प्रणाली की आवश्यकता है, लेकिन यह एक वेब-विशिष्ट बाधा की तरह लगता है, डोमेन आवश्यकता नहीं है। लेकिन समानता के लिए, मुझे ऐसा नहीं लगता है कि विभिन्न सत्रों से वस्तुओं की तुलना करने का एक कारण है। –

+0

इकाई-ऑफ-वर्क या सत्र पैटर्न की आवश्यकता होगी, यहां तक ​​कि डेटाबेस के बिना डेस्कटॉप ऐप में भी, आपके डोमेन मॉडल ऑब्जेक्ट्स में अनन्य निरंतर पहचानकर्ता होते हैं जो पूरे सत्र में समान होते हैं, भले ही ऑब्जेक्ट्स सत्रों में समान नहीं हों। – yfeldblum