2009-05-29 12 views
7

यह मेरे प्रश्न here पर अवधारणा से संबंधित है। हालांकि, मैं एनएचबेर्नेट के साथ खेल रहा हूं, और महसूस किया कि मेरे प्रश्न का असली मूल क्या है।क्या कोई भी .NET ORM रचनाकारों का "ठीक से" उपयोग करता है?

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

क्या वहां कोई .NET ओ/आरएम समाधान है जो ऐसा करता है?

संपादित

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

+0

एक और दिलचस्प सवाल है: क्या कन्स्ट्रक्टर में कुछ व्यावसायिक तर्क शामिल हो सकते हैं? अर्थात। जब मैं कक्षा ए का उदाहरण बनाता हूं तो इसका कन्स्ट्रक्टर लगातार कक्षा बी का उदाहरण बना सकता है और इसे निजी सेटर के साथ संपत्ति में असाइन कर सकता है। –

+1

@Alex: मेरा लक्ष्य है कि डोमेन ऑब्जेक्ट्स अज्ञान रहें। डोमेन ऑब्जेक्ट से एक दृढ़ता ऑब्जेक्ट बनाने के लिए तर्क होने का उल्लंघन करता है, और दृढ़ता से डोमेन ऑब्जेक्ट को दृढ़ता विधि पर जोड़ता है - एक और खराब बात। –

उत्तर

1

जोव द्वारा, मुझे लगता है कि मुझे यह मिल गया है!

उनके इनपुट के लिए सभी को धन्यवाद, लेकिन मुझे अपने स्वयं के प्रश्न का उत्तर देना होगा। मैंने ओओ सिद्धांतों पर विचार करते हुए PoEAA catalog के माध्यम से एक घंटे या तो खुदाई की, और सी # भाषा और .NET ढांचे के बारे में गहरे विचार के साथ मिश्रण किया।

उत्तर के साथ आया, एक की आवश्यकता है कि मैं रचनाकारों का उपयोग करके ठीक तरह से हल नहीं कर पा रहा हूं, अंत में निर्माता से संबंधित नहीं हो रहा है। यह lazy loading है!

मूल रूप से, आपके डोमेन वर्गों (दृढ़ता अज्ञानता और लचीलापन के लिए एक प्रमुख नो-नो) के अंदर आलसी लोडिंग को लागू किए बिना, डोमेन कक्षाओं को उप-वर्गीकृत किए बिना ऐसा करने का कोई तरीका नहीं है। यह सबक्लासिंग कारण है कि NHibernate को वर्चुअल गुणों की आवश्यकता होती है।

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

+0

मैं वास्तव में उस निष्कर्ष को समझ नहीं पा रहा हूं जो आप यहां आए थे ... क्या आपको लगता है कि डोमेन ऑब्जेक्ट्स के लिए डिफ़ॉल्ट कन्स्ट्रक्टर होना ठीक है, क्योंकि यह डोमेन के बारे में कुछ व्यक्त करता है, जैसे। कि वस्तुओं आलसी लोड होने में सक्षम हैं? यह अभी भी दृढ़ता से संबंधित प्रतीत होता है, डोमेन तर्क नहीं ... – Domenic

+0

मेरा निष्कर्ष यह है कि "यांत्रिक" मुद्दे शामिल हैं जो लागू करने के लिए "शुद्धवादी" दृष्टिकोण को असंभव नहीं बनाते हैं। मुझे अभी भी यह वास्तव में पसंद नहीं है, लेकिन मेरे व्यावहारिक पक्ष चीजों को पूरा करने के लिए इसके साथ जाने के लिए तैयार हैं। –

2

दुर्भाग्यवश, बिना किसी तरीके से कन्स्ट्रक्टर को चिह्नित किए बिना यह .NET में असंभव है।

असेंबली मेटाडाटा में प्रत्येक कन्स्ट्रक्टर के लिए संग्रहीत विधि हस्ताक्षर केवल कन्स्ट्रक्टर को प्रत्येक पैरामीटर का प्रकार होता है। किसी भी .NET ORM के लिए वास्तव में यह जानने के लिए कोई तरीका नहीं है कि किस कन्स्ट्रक्टर का उपयोग करना है।

.ctor() 
.ctor(string, string) 
.ctor(string, string, string) 

वहाँ के लिए ORM पता करने के लिए जो .ctor पैरामीटर उदाहरण के लिए अपने ग्राहकों की वस्तु के लिए प्रथम नाम, अंतिम नाम और MiddleName से मेल खाती है कोई रास्ता नहीं है: सभी ORM देखता है कुछ इस तरह है।

आपको यह समर्थन देने के लिए, एक .NET ORM को प्रत्येक पैरामीटर के लिए परिभाषित कस्टम विशेषताओं में पढ़ने का समर्थन करना चाहिए। आपको अपने रचनाकारों को इस तरह मार्कअप करने की आवश्यकता होगी:

सार्वजनिक ग्राहक ([संपत्ति ("फर्स्टनाम")] स्ट्रिंग फर्स्टनाम, [संपत्ति ("अंतिम नाम")] स्ट्रिंग LastName, [संपत्ति ("MiddleName")] स्ट्रिंग MiddleName)

2 नुकसान हैं:

  1. वहाँ कोई रास्ता नहीं है (है कि मैं के बारे में सोच सकते हैं कि, किसी ने शायद मुझे सही कर देंगे), कि यह एक मानचित्रण फाइल में जा सकते हैं।
  2. आपको अभी भी वही मानचित्रण लिखना होगा जैसा आपने हमेशा किया है, क्योंकि ओआरएम को अभी भी प्रत्येक संपत्ति के लिए व्यक्तिगत मान प्राप्त करने में सक्षम होना चाहिए।

तो आपको रचनाकारों को चिह्नित करने के लिए यह अतिरिक्त कार्य करने की आवश्यकता होगी और साथ ही, आपको अभी भी अपनी कक्षाओं को मैप करना होगा जैसा कि आप पहले कर रहे थे।

+1

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

+1

"असेंबली मेटाडाटा में प्रत्येक कन्स्ट्रक्टर के लिए संग्रहीत विधि हस्ताक्षर" में पैरामीटर नाम भी शामिल है, न केवल इसके प्रकार। ओआरएम बिना मैपिंग (कॉन्फ़िगरेशन पर सम्मेलन) की आवश्यकता के बिना गुणों के आधार पर गुणों से मिलान कर सकता है। हालांकि, अभी भी सीटीओ का उपयोग करने का मुद्दा है। – Lucas

+0

@ लुकास: बहुत सच - .NET परावर्तक पैरामीटर के नाम दिखाता है। कौन जानता है - शायद मुझे अभी एक खुजली मिली है जिसे मुझे यहां खरोंच करने की ज़रूरत है। –

3

मुझे लगता है कि ज्यादातर ओआरएम वास्तव में इस अवधारणा का समर्थन करते हैं, कम से कम DataObject.Net करता है।इस कोड काम करता है के रूप में यह उम्मीद:

[HierarchyRoot(typeof(KeyGenerator), "Id")] 
public class Message : Entity 
{ 
    [Field] 
    public int Id { get; private set; } 

    [Field(Length = 100)] 
    public string Text { get; private set; } 

    public Message(string Text) 
    { 
    Text = text; 
    } 
} 

संपादित करें: आंतरिक लेन-देन संबंधी राज्य में DataObjects दुकान डेटा, और विशेष भौतिकीकरण निर्माता, PostSharp द्वारा उत्पन्न का उपयोग करें। बेशक यह ओआरएम पॉको ऑब्जेक्ट्स का उपयोग करते समय इतना छोटा नहीं है।

0

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

यह निश्चित रूप से संभव है, मैं एक ओआरएम का उपयोग करता हूं जिसे मैंने लिखा है, और अगर आप केवल पढ़ने योग्य संपत्ति के मूल्य को सेट करने का प्रयास करते हैं तो यह अपवाद फेंकता है।

अद्यतन:

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

+0

यदि यह गुण बना रहा है, तो क्या यह ओ/आरएम (या यह दोनों है) की बजाय कोड जनरेटर नहीं बनायेगा? –

+0

यह दोनों है! ऐसा कोई नियम नहीं है कि एक ओआरएम गतिशील रूप से मैपिंग उत्पन्न करे। – RedFilter

+1

यदि आपका पीके एक सरोगेट कुंजी है, तो एक कन्स्ट्रक्टर में पीके का उपयोग करके, मेरे लिए, कोड गंध का थोड़ा सा होना चाहिए। यदि * व्यवसाय * कुंजी पीके है, तो इससे थोड़ा और समझ आता है, लेकिन उस मामले में मैं सुझाव दूंगा कि ऑब्जेक्ट का निर्माण गलत दृष्टिकोण है - पीके को एक भंडार में पास करना एक बेहतर मार्ग होगा। –

0

यह सामान्य मामले में है - केवल एक निर्माता के लिए या मैपर के लिए संभव नहीं है। उस ऑब्जेक्ट को मानें जो कि निर्माता को पास किए गए मानों द्वारा प्रारंभ किया गया है और उसके बाद विधि विधि कॉल द्वारा संशोधित किया गया है। इस मामले में ऑब्जेक्ट को ऐसे राज्य के साथ जारी रखा जा सकता है जो वैध प्रारंभिक स्थिति नहीं है और इसलिए निर्माता द्वारा अस्वीकार कर दिया गया है।

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

+1

मैं इसे एक वैध तर्क के रूप में नहीं देख सकता। यदि किसी ऑब्जेक्ट की स्थायी स्थिति किसी निर्माता के लिए मान्य है, तो यह किसी ऑब्जेक्ट के जीवनकाल में किसी भी बिंदु के लिए मान्य होना चाहिए। किसी भी वस्तु जिसका वैध राज्य अपने जीवनकाल के दौरान बदलता है, वह ऐसा कुछ होने की संभावना है जो आप जारी नहीं रखते (या केवल आंशिक रूप से बने रहें), या शायद रिफैक्टरिंग की आवश्यकता में। –

+0

तर्क दूसरी दिशा में जाता है - जीवन काल के दौरान मान्य एक राज्य निर्माण समय पर मान्य रूप से मान्य नहीं है। एक उदाहरण के रूप में एक जीवन चक्र प्रबंधन प्रणाली के रूप में ले लो, शायद परियोजनाओं के लिए। वे हमेशा प्रारंभिक स्थिति के साथ बनाए जाते हैं और फिर जब तक आप एक पूर्ण, बंद, या संग्रहीत स्थिति तक नहीं पहुंच जाते हैं तब तक राज्य बदल जाता है। आपको एक ऐसे संरक्षक की भी आवश्यकता नहीं है जो राज्य को तर्क के रूप में ले जाए क्योंकि राज्य हमेशा प्रारंभिक स्थिति है। लेकिन निश्चित रूप से आप किसी भी राज्य में परियोजना को जारी रखने और पुनर्प्राप्त करने में सक्षम होना चाहिए। –

+1

मुझे लगता है कि आपका दावा गलत है - मुझे कोई कारण नहीं दिखता कि एक प्रोजेक्ट ऑब्जेक्ट को खुले, समाप्त, संग्रहीत, या किसी अन्य * वैध * स्थिति में तत्काल क्यों नहीं किया जा सका। यदि किसी प्रोजेक्ट को समाप्त होने तक संग्रहीत नहीं किया जा सकता है, तो एक समाप्ति स्थिति के साथ एक संग्रहीत स्थिति है जो अभी तक नहीं हुई है, अमान्य है, लेकिन एक नया तत्काल प्रोजेक्ट होने पर संग्रहीत राज्य में होना जरूरी नहीं है। 'लालची' कन्स्ट्रक्टर चयन विधि वास्तव में इसका भी समर्थन करेगी (कम- या कोई-Arg ctor डिफ़ॉल्ट रूप से नहीं चुना जाएगा, लेकिन अगर यह समझ में आता है तो उपलब्ध हो)। –

1

आपको ऐसा क्यों लगता है कि यह गलत लगता है? क्या आप ऑब्जेक्ट का पुनर्गठन करते समय अपना OR/M व्यवसाय तर्क निष्पादित करना चाहते हैं? आईएमएचओ, नहीं।

जब आप डीबी से ऑब्जेक्ट लोड करते हैं, तो OR/M ऑब्जेक्ट का पुनर्गठन करने में सक्षम होना चाहिए, इससे कोई फर्क नहीं पड़ता। पुनर्विचार करते समय कुछ मूल्य निर्धारित करना, किसी प्रकार का तर्क ट्रिगर नहीं करना चाहिए जो किसी अन्य मूल्य को बदलता है (जिसे शायद ओआरएम द्वारा भी मूल्य दिया जाना चाहिए ...)

फिर भी, मुझे लगता है कि एक निर्माता में केवल होना चाहिए उन क्षेत्रों के पैरामीटर जो ऑब्जेक्ट-निर्माण समय पर अनिवार्य हैं, ऑब्जेक्ट को 'वैध' स्थिति में रखने के लिए। इसके आगे, आपके पास सार्वजनिक पढ़ने-योग्य गुण हो सकते हैं जिन्हें कुछ गणना द्वारा मूल्य दिया गया है, और इसे भी जारी रखने की आवश्यकता है।
यदि आपको लगता है कि प्रतिबिंब वस्तुओं को पुनर्स्थापित करने के लिए 'गंध' है, तो आप इस स्थिति से कैसे निपटेंगे? आपको किसी भी तरह से एक सार्वजनिक विधि बनाना होगा जो 'केवल पढ़ने' मान को सेट करने में सक्षम होगा, लेकिन यह encapsulation तोड़ता है, और आप इसे भी नहीं चाहते हैं।

+1

गणना द्वारा बनाई गई किस तरह की सार्वजनिक पढ़ने-योग्य संपत्ति मौजूद होगी, यह एक वस्तु के बने राज्य का हिस्सा नहीं है? गणना किस डेटा पर काम करेगी? यदि यह ऑब्जेक्ट से डेटा है, तो आप इसे आसानी से पुनर्निर्माण कर सकते हैं। यदि यह ऑब्जेक्ट के बाहर डेटा है, तो मैं तर्क दूंगा कि या तो डेटा या रीड-ओनली फ़ील्ड गलत जगह पर है। –

+0

@ हार्पर: "यदि यह ऑब्जेक्ट से डेटा है, तो आप आसानी से इसे पुनर्स्थापित कर सकते हैं", सुविधाजनक पढ़ने-योग्य संपत्ति में! यह एक डीबी – Lucas

+0

में गणना की गई कॉलम के समान है या, आपके ऑब्जेक्ट में आपके पास 'स्थिति' ध्वज के कुछ भाग्य के बारे में क्या है। मान लीजिए कि आपके पास एक फ़्लैग 'PropertyChanged' है जिसे आपने सेट किया है जब भी उपयोगकर्ता कोई संपत्ति बदलता है, लेकिन जब आप ऑब्जेक्ट को डीबी से लोड करते हैं तो आप यह ध्वज सेट नहीं करना चाहते हैं। –

0

श्री स्कीट ने कुछ समय पहले 'बिल्डर' पैटर्न का सुझाव दिया था। मैंने इसे पीओसीओ कक्षा के भीतर एक सार्वजनिक वर्ग बना दिया। इसमें पीओसीओ के समान गुण हैं, लेकिन सभी पढ़/लिखते हैं। जहां आवश्यक हो, पीओसीओ पढ़ा जाता है, लेकिन निजी सेट। इस तरह जब निर्माता पीओसीओ को तत्कालित किया जाता है और कन्स्ट्रक्टर के लिए फंकी तर्क नहीं होता है तो निर्माता उचित सेट कर सकता है। वहाँ 'popcicle अपरिवर्तनीयता' की तरह।

+0

ऐसा लगता है कि यह DRY सिद्धांत का उल्लंघन करता है - मैं व्यक्तिगत रूप से दोहराव वाले कार्यों का विरोध करता हूं, खासकर जब मुझे लगता है कि वे वास्तव में सही दृष्टिकोण नहीं हैं। –

+0

मैं समझता हूं। कन्स्ट्रक्टर-पैरामीटर दृष्टिकोण के बारे में मुझे क्या बग है यह मेरे लिए उचित जगहों को सूचीबद्ध करने के लिए एक और जगह है। कन्स्ट्रक्टर पैराम्स उन्हें सूचीबद्ध करते हैं; कन्स्ट्रक्टर सेटिंग निजी फ़ील्ड उन्हें सूचीबद्ध करता है; और खेतों को खुद ... एक पार्मेटर बदलना है? brrrr – n8wrl

+0

हाँ ... यहां तक ​​कि सी ++ विधि (प्रारंभकर्ता सूचियां) * अधिक * बेहतर नहीं है। हालांकि, कन्स्ट्रक्टर पैरामीटर दृष्टिकोण ओओ सिद्धांतों से मेल खाने के करीब आता है, जिसे मुझे दिन में वापस लाया गया था (ठीक है, 10 साल पहले - मैं बूढ़ा नहीं हूँ!)। –

1

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

इस बिंदु पर क्या विचार किया जाना चाहिए, और सभी प्रमुख ओआरएम क्या खो रहे हैं, यह है कि किसी डेटाबेस या किसी अन्य डेटा स्टोर में संग्रहीत के रूप में अपने अंतिम ज्ञात राज्य से डोमेन ऑब्जेक्ट को फिर से गठित करना, नहीं है स्वाभाविक रूप से एक निर्माण या संशोधन ऑपरेशन; इसलिए न तो रचनाकारों या संपत्ति सेटर्स का उपयोग किया जाना चाहिए। इसके बजाय, फ्रेमवर्क तंत्र जो इस तरह के ऑपरेशन से सबसे करीबी रूप से मेल खाता है वह धारावाहिक है! ऑब्जेक्ट के राज्य को संग्रहीत करने के लिए पहले से ही मान्यता प्राप्त पैटर्न हैं और बाद में इसे आईएसरियलज़ेबल इंटरफ़ेस, मानक क्रमबद्धता कन्स्ट्रक्टर इत्यादि के माध्यम से पुन: स्थापित कर रहे हैं। डेटाबेस में ऑब्जेक्ट को रखने से मूल रूप से स्ट्रीम में इसे रखने से कोई अलग नहीं होता है; वास्तव में, StreamingContextStates गणना के मानों में से एक जिसका उपयोग serialization के दौरान किया जाता है दृढ़ता है! आईएमएचओ, किसी भी दृढ़ता तंत्र को डिजाइन करते समय यह मानक दृष्टिकोण होना चाहिए। दुर्भाग्यवश, मुझे किसी भी ओआरएम की जानकारी नहीं है जो बॉक्स के बाहर इसका समर्थन करता है।

यह भी ध्यान दिया जाना चाहिए कि एक वस्तु जिसे क्रमबद्ध करने के लिए डिज़ाइन किया गया है अभी भी पॉको है; दृढ़ता अज्ञानता का उल्लंघन नहीं किया गया है। यहां मुख्य बिंदु यह है कि एक डोमेन ऑब्जेक्ट को यह पता होना चाहिए कि इसे जारी रखने और उसे पुनर्स्थापित करने के लिए डेटा के साथ-साथ किस क्रम में डेटा को बहाल किया जाना चाहिए (जो अक्सर मायने रखता है)। वस्तु को क्या पता होना चाहिए कि वह विशिष्ट तंत्र है जिसके द्वारा इसे संग्रहीत किया जाएगा: संबंधपरक डेटाबेस, फ्लैट फ़ाइल, बाइनरी ब्लॉब, आदि

+1

आईएसरियलज़ेबल अस्तित्व से काफी पहले, यह वस्तुओं को deserialize करने के लिए रचनाकारों का उपयोग करने के लिए आम था (और बिल्कुल counterintuitive नहीं!)। एक कन्स्ट्रक्टर किसी ऑब्जेक्ट का उदाहरण बनाता है - कन्स्ट्रक्टर कॉल और * डोमेन इकाई * के जीवनकाल में कोई अंतर्निहित टाई नहीं है। ऑब्जेक्ट, हाँ ... लेकिन ऑब्जेक्ट डोमेन इकाई का * प्रतिनिधित्व * है, न कि इकाई स्वयं। –

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