2009-10-23 16 views
14

में शामिल हो रहा है, मैं अपने आवेदन की मॉडल परत के लिए प्रोग्रामिंग/डिज़ाइन पैटर्न देख रहा हूं, और यह सोच रहा हूं कि आप किस स्थिति में पुनर्प्राप्ति कर रहे हैं जिसमें कई तालिकाओं में शामिल होना शामिल है।डेटाबेस तालिका के लिए सर्वश्रेष्ठ डिज़ाइन पैटर्न

उदाहरण के लिए, मान लीजिए आप निम्न तालिकाओं/संबंध: ग्राहक -> 1..n लेखा -> 0..n सुविधाएँ

जहां एक फ़ीचर चेक बुक किया जा सकता है, या कुछ प्रीमियम उत्पाद मुफ्त यात्रा बीमा की तरह।

फिर मैं उन ग्राहकों के साथ सभी ग्राहकों को पुनर्प्राप्त करने के लिए क्लाइंटर्सफॉरफ़ेचर() प्राप्त करना चाहता हूं, जिनमें निःशुल्क यात्रा बीमा है।

ActiveRecord या डेटा एक्सेस ऑब्जेक्ट का उपयोग करने के लिए उपयुक्त नहीं लगता है, क्योंकि ये आम तौर पर प्रति वर्ग एक वर्ग पर ध्यान केंद्रित करते हैं; इसी प्रकार डेटा मैपर के लिए। मुझे एहसास है कि मैं इसे प्रत्येक तालिका के लिए संचालन में तोड़ सकता हूं, उदा। GetAccountsForFeature() और getCustomersForAccount() प्राप्त करें, लेकिन मैं एक हिट में पुनर्प्राप्ति करना चाहता हूं।

यदि हम एक-वर्ग-प्रति-तालिका पैटर्न को "झुकाव" करना चाहते हैं और डेटा एक्सेस ऑब्जेक्ट पैटर्न का उपयोग करना चाहते हैं, तो कहें, क्या ग्राहक कस्टमर्सफोरफ़ेचर() विधि ग्राहकदाओ या फ़ीचरडीओ पर जाना चाहिए? लेकिन यह मेरे लिए सही नहीं लगता है क्योंकि आप अन्य डीएओ के ज्ञान के साथ अपने डीएओ को प्रदूषित करेंगे।

सुझाव कृपया।

+0

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

उत्तर

1

सी #/लिंक से एसक्यूएल में यह निम्न की तरह कुछ होगा। (मुझे लगता है कि वास्तव में फीचर प्रकारों की एक लुकअप टेबल है, ताकि आपके पास अपने फीचर प्रकारों की एक मानक सूची हो और फिर खाते में उनका रिश्ते अलग हो, इसलिए फीचरटाइप आईडी आपका एफके वैल्यू होगा, शायद ड्रॉप-डाउन से चुना गया हो सूची या कुछ और।)

// or whatever data type your keys are in 
public IEnumerable<Customer> getCustomersForFeature(int featureTypeId) 
{ 
    return from feature in dbContext.Features 
      where feature.FeatureTypeId == featureTypeId 
      select getCustomer(feature.Account.Customer.Id); 
} 

कुछ स्तर अपने डीएओ/बाओ अपने वस्तुओं के बीच संबंधों के बारे में पता होना जरूरी है, तो तथ्य यह है कि यह एक दादा-दादी संबंध भी डरावना नहीं होना चाहिए है।

जहां यह आपकी बीएओ संरचना में है, एक तर्क शायद किसी भी तरह से बनाया जा सकता है। मैं शायद इसे ग्राहक पर रखूंगा, क्योंकि आखिरकार मैं कहां जा रहा हूं।

संपादित करें: जैसा कि टोबी ने बताया, रिश्ते द्विपक्षीय हैं; फिर Linq में, आप अन्य तरीके के रूप में अच्छी तरह से जा सकते हैं:

// or whatever data type your keys are in 
public IEnumerable<Customer> getCustomersForFeature(int featureTypeId) 
{ 
    return from customer in dbContext.Customers 
      from account in customer.Accounts 
      from feature in account.Features 
      where feature.FeatureTypeId == featureTypeId 
      select getCustomer(customer.Id); 
} 

किसी भी अन्य ORM बहुत समान व्यवहार होना चाहिए, भले ही वाक्य रचना और संरचना अलग अलग होंगे।

2

रेल मॉडलों में सक्रिय रिकॉर्ड जिस तरह से ग्राहक ऑब्जेक्ट को_many खातों की अनुमति दे रहा है - जो मूल रूप से खाता ऑब्जेक्ट्स के संग्रह में अनुवाद करता है, जिसके बदले में सुविधाओं का संग्रह होता है। संबंध बिडरेक्शनल हो सकते हैं, इसलिए प्रत्येक एआर मॉडल आपकी आवश्यकताओं के आधार पर इसके संबंधों के बारे में "जान" सकता है।

मुझे लगता है कि किसी ऑब्जेक्ट के लिए अन्य टेबलों के बारे में ज्ञान होना ठीक है, क्योंकि ऐसे संबंध ओओ और आरडीबीएमएस/एसक्यूएल दोनों के लिए मौलिक हैं।

+0

प्लस आप has_many के साथ सुविधाओं को परिभाषित कर सकते हैं: उपयोगकर्ता,: through => खाते। –

+0

क्या आप विस्तृत कर सकते हैं कि मैपिंग कवर के तहत कैसे किया जाता है, उदा। ग्राहक खाते को स्वचालित रूप से पुनर्प्राप्त करने के लिए संबंधित खातों और सुविधाओं को पुनर्प्राप्त कर रहा है (यानी 3 टेबलों में शामिल होना) या ये आलसी लोड हैं? अगर मैं ग्राहक/खाता/फ़ीचर के * कुछ * विशेषताओं (यानी सबसेट) को पुनर्प्राप्त करना चाहता हूं लेकिन पूरे ऑब्जेक्ट ग्राफ़ को नहीं, तो मैं यह कैसे करूँगा? –

+0

रेल में सक्रिय रिकॉर्ड बहुत परिष्कृत है। डिफ़ॉल्ट व्यवहार यह है कि संग्रह आलसी लोड हो जाएगा, जिसका अर्थ अतिरिक्त प्रश्न हो सकता है। हालांकि प्रारंभिक खोज पर "शामिल" तंत्र का उपयोग करके डेटा उत्सुक हो सकता है (इसलिए जब आप कोई ग्राहक लोड करते हैं, तो आप इसे खाते को लोड करने के लिए कहते हैं और एआर आपके लिए एक जॉइन तैयार करेगा)। विशिष्ट फ़ील्ड भी लोड किए जा सकते हैं - आप बस इसे बताएं कि कौन से फ़ील्ड लोड हो सकते हैं। –

0

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

एक बार आपके पास एक अच्छा डेटा मॉडल हो जाने पर, यदि ActiveRecord या DAO आपके इच्छित तरीके से इसका उपयोग नहीं करेगा, तो उन्हें SQL लिखकर बाईपास करें।

ऑब्जेक्ट रिलेशनल मैपिंग डेटाबेस के साथ प्रोग्रामिंग को आसान बनाना है, लेकिन क्योंकि या मॉडल के बीच अंतर, कभी-कभी सरल तरीका सीधे एसक्यूएल पर जाना है।

+0

मैं ओआरएम इत्यादि को अनदेखा करने से सावधान हूं क्योंकि मैं डेटाबेस को/से जितना संभव हो उतना स्थानों पर मैप करना है (अधिमानतः एक) के बारे में ज्ञान को समाहित करना चाहता हूं। दुःस्वप्न परिदृश्य डेटाबेस संरचना को बदल रहा है और फिर सभी प्रभावित प्रश्नों को ढूंढ रहा है। आप ActiveRecord/DAO पर क्या सीमाएं (यदि कोई हैं) लगा रहे हैं, उदा। प्रति वर्ग एक वर्ग? –

+1

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

0

गैलेक्टिककॉबॉय से सहमत है कि ओआरएम ऑब्जेक्ट उन्मुख प्रश्नों से डेटाबेस क्लास मैपिंग विवरण को अलग करने की अनुमति देता है। बस जावा हाइबरनेट ORM के लिए एक उदाहरण प्रदान करना चाहते हैं - तरीके association mappings और परिभाषित करने के लिए की संख्या

ग्राहक ग बाएं से

ग चयन c.accounts एक छोड़ दिया में शामिल होने के शामिल होने वस्तु उन्मुख HQL क्वेरी निम्नलिखित उनमें से सब से ऊपर ठीक काम करता है देखते हैं च a.features जहां f.name = 'कूल'

ध्यान दें कि 'ग्राहक' यहाँ एक वर्ग के नाम और 'c.accounts', 'a.features' और 'च है। नाम ' कक्षा-स्तर के संपत्ति नाम हैं, यानी कोई डेटाबेस-विशिष्ट विवरण यहां उल्लेखित नहीं हैं।

8

Model-Driven Design में, आपके पास आपके आवेदन में तार्किक इकाइयां है, और ये संस्थाएं भौतिक डेटाबेस में एकाधिक तालिकाओं को मैप कर सकती हैं। बेशक आपको एक पूर्ण इकाई लाने के लिए अधिक जटिल एसक्यूएल चलाने की जरूरत है, और मॉडल क्लास वह जगह है जहां इन रिश्तों को लागू किया जाता है।

मुझे लगता है कि ActiveRecord और उनके जैसे एक ही टेबल के खिलाफ सरल प्रश्नों के लिए उपयोग करने के लिए ठीक हैं, लेकिन जटिल प्रश्नों के लिए इन पैटर्नों का उपयोग करने के लिए बल की कोशिश करना बहुत मुश्किल है। सौभाग्य से, हमारे पास पहले से ही एक संक्षिप्त, डोमेन-विशिष्ट भाषा है जिसका उपयोग आप जटिल प्रश्नों को निर्दिष्ट करने के लिए कर सकते हैं: एसक्यूएल।

तो आपके मॉडल वर्ग में, आपके पास getCustomersForFeature() जैसे लॉजिकल एप्लिकेशन-स्तरीय कार्यों को करने के तरीके होंगे। उस विधि के कोड में, आपको एक विशिष्ट क्वेरी लिखनी चाहिए, या तो ActiveRecord विधियों के साथ या यदि आवश्यक हो तो सीधे SQL के साथ। इस प्रकार मॉडल डेटाबेस में, आपके डेटाबेस का कंक्रीट डिज़ाइन एक ही स्थान पर encapsulated है।

इसका मतलब है कि हमें मॉडल और तालिका के बीच युग्मन को तोड़ने की आवश्यकता है। एक मॉडल और एक ActiveRecord वर्ग के बीच ओओ संबंध आईएस-ए है - यह हैस-ए (या कई है)।


आपकी टिप्पणी दो: तो हमारा मॉडल क्या है? यदि आपके आवेदन को मुख्य रूप से ग्राहकों के साथ एक इकाई के रूप में काम करने की ज़रूरत है, और ग्राहकों की विशेषता कम या ज्यादा सुविधाओं के साथ व्यवहार करती है, तो हाँ आपका मॉडल ग्राहक होगा, और यह इस तथ्य को छुपाएगा कि डेटाबेस डेटाबेस में एक अलग तालिका में संग्रहीत हैं । ग्राहक मॉडल आंतरिक रूप से जटिल डेटा का पूरा दृश्य प्रदान करने के लिए आवश्यक डेटा इकट्ठा करने के लिए ActiveRecord या plain SQL का उपयोग करेगा जो उसके संबंधित बहु-मूल्यवान गुण वाले ग्राहक हैं।

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

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

लेकिन आपके ग्राहक मॉडल और आपके फीचर मॉडल बनाने के बाद, क्या यह तर्क के दोहराव का कारण बनता है जो तालिकाओं के बीच संबंधों के बारे में जानता है? हाँ, यह हो सकता है। यह object-relational impedance mismatch के दायरे में आने वाली कई समस्याओं में से एक है।

+0

समझ में आता है। तो मैंने जो उदाहरण दिया है, क्या आप केवल एक ग्राहक मॉडल बनाने का प्रस्ताव देंगे? –

0

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

और आपके कहने के बारे में 'मैं एक हिट में पुनर्प्राप्ति करना चाहता हूं। ', मुझे लगता है कि आपको कस्टम एसक्यूएल क्वेरी लिखना चाहिए या शायद LINQ का उपयोग करना चाहिए।

0

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

ओआरएम मॉडल अभी तक एक अमूर्त है।

+0

हां और नहीं। हां, क्योंकि कुछ ऐसे मामले हैं जहां कोई क्वेरी व्यक्त करने के लिए ओआरएम एपीआई का उपयोग नहीं कर सकता है, और नहीं, क्योंकि यदि आपके पास शक्तिशाली ओआरएम (हाइबरनेट/एनएचबीरनेट) है तो यह मामला कम है और इसके एपीआई को काफी अच्छा पता है। मुझे लगता है कि आप ओआरएम द्वारा प्रदान किए गए अधिकांश फायदों को खो देते हैं यदि आप इसे केवल सबसे सरल सीआरयूडी परिचालनों के लिए उपयोग करते हैं। – Max

0

आवश्यकताएं ओटेन आपके लिए यह तय करती है। या तो आपकी समय सीमा, आपकी कार्य संस्कृति या आपकी परियोजना आवश्यकताओं के द्वारा। आपकी समय सीमा "उपकरण टू कोड" और कटौती सुविधाओं को इंगित कर सकती है। आपके कर्मचारियों को "कोई नई पुस्तकालय या विफलता मोड" की आवश्यकता हो सकती है। अपने पर्यावरण में, आप मुझे यह कहानी सुनाई देंगे:

"... यह नई ओआरएम पुस्तकालयों को पेश करने के लिए नहीं करेगा, इसलिए वे बाहर हैं। डेडलाइन इंगित करेंगे कि मुझे खुद को पढ़ाना शुरू नहीं करना चाहिए serializing पूरे टेबल पर एसक्यूएल विचारों का उत्पादन करने के लिए। मेरे कार्य संस्कृति को सूचित मुझे इसे जल्दी से किया जाना। मेरे वास्तुकला कराहना और मेरे प्रदर्शन की आवश्यकताओं से संकेत मिलता है मैं इस डेटा ... "

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

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

3

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

मैंने एंटरप्राइज़ एप्लिकेशन आर्किटेक्चर के पैटर्न की मेरी प्रतिलिपि पर भी एक और नजर डाली, और ऐसा लगता है कि ActiveRecord पैटर्न क्लास के डेटाबेस तालिका के प्रत्यक्ष मैपिंग के लिए है, यदि आपने डीडीडी से रिपोजिटरी दृष्टिकोण का पालन नहीं करना चुना है तो डेटा मैपर एक समग्र मैपिंग के लिए उपयुक्त होगा।

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

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