2008-09-05 16 views
38

उदाहरणआप डेटाबेस में polymorphism से कैसे निपटते हैं?

मैं Person, SpecialPerson, और User है। Person और SpecialPerson सिर्फ लोग हैं - उनके पास साइट पर कोई उपयोगकर्ता नाम या पासवर्ड नहीं है, लेकिन वे रिकॉर्ड रखने के लिए डेटाबेस में संग्रहीत हैं। उपयोगकर्ता के पास Person और संभावित रूप से SpecialPerson, उपयोगकर्ता नाम और पासवर्ड के साथ साइट के साथ पंजीकृत सभी डेटा समान डेटा हैं।


आप इस समस्या का समाधान कैसे करेंगे? क्या आपके पास Person तालिका है जो किसी व्यक्ति को आम डेटा को संग्रहीत करती है और SpecialPerson (यदि वे एक विशेष व्यक्ति हैं) और उपयोगकर्ता (यदि वे उपयोगकर्ता हैं) में इसके डेटा को देखने के लिए कुंजी का उपयोग करते हैं और इसके विपरीत?

उत्तर

35

डेटाबेस टेबल पर ऑब्जेक्ट विरासत मैपिंग के आम तौर पर तीन तरीके हैं।

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

आप बेस-क्लास फ़ील्ड वाले सभी टेबलों के साथ सभी अलग-अलग बाल वर्गों के लिए अलग-अलग टेबल बना सकते हैं। यह एक प्रदर्शन परिप्रेक्ष्य से ठीक है। लेकिन एक रखरखाव परिप्रेक्ष्य से नहीं। प्रत्येक बार जब आपकी बेस-क्लास बदल जाती है तो सभी टेबल बदल जाते हैं।

आप सुझाए गए अनुसार प्रति कक्षा एक टेबल भी बना सकते हैं। इस तरह आपको सभी डेटा प्राप्त करने के लिए शामिल होने की आवश्यकता है। तो यह कम प्रदर्शनकारी है। मुझे लगता है कि यह सबसे साफ समाधान है।

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

+0

जब आप कहते हैं कि यह तेज़ है लेकिन spaces_ को बर्बाद कर देता है, तो क्या आपका मतलब तेजी से विकसित करना या प्रदर्शन-वार तेज़ होना है? – user3748908

+0

दोनों, सभी डेटा एक तालिका में हैं (विकल्प 3 के विपरीत) इसलिए कोई भी शामिल होने की आवश्यकता नहीं है ताकि पढ़ने और लिखने के लिए उचित रूप से तेज़ हो, और यह विकसित करना आसान हो। अधिकांश या मैपर इस तरह की योजनाओं का समर्थन करते हैं। – Mendelt

+0

तालिका-प्रति-प्रकार (जॉइन की वजह से) की तुलना में तेज़, लेकिन तालिका-प्रति-कंक्रीट की तुलना में धीमी है, क्योंकि तालिका-प्रति-कंक्रीट की तालिकाएं छोटी हैं और आप शायद ही कभी एक-दूसरे के साथ जुड़ने जा रहे हैं, सही ? – user3748908

0

व्यक्तिगत रूप से, मैं इन सभी अलग-अलग उपयोगकर्ता कक्षाओं को एक ही तालिका में स्टोर करूंगा। फिर आप या तो एक फ़ील्ड कर सकते हैं जो 'टाइप' मान संग्रहीत करता है, या आप यह बता सकते हैं कि आप किस प्रकार के व्यक्ति से निपट रहे हैं, किस फ़ील्ड भर रहे हैं। उदाहरण के लिए, यदि उपयोगकर्ता आईडी पूर्ण है, तो यह रिकॉर्ड एक नहीं है उपयोगकर्ता।

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

यदि आप उस मार्ग पर जाने का निर्णय लेते हैं तो वे पहली विधि LINQ-to-SQL द्वारा समर्थित हैं (वे इसे 'टेबल प्रति पदानुक्रम' या 'टीपीएच' कहते हैं)।

0

अतीत में मैंने इसे ठीक से किया है जैसा कि आप सुझाव देते हैं - आम सामान के लिए एक व्यक्ति तालिका है, फिर व्युत्पन्न वर्ग के लिए स्पेशलपर्सन लिंक किया गया है। हालांकि, मैं फिर से सोच रहा हूं कि, जैसा कि Linq2Sql एक ही तालिका में एक फ़ील्ड रखना चाहता है, अंतर को इंगित करता है। मैंने इकाई मॉडल को बहुत अधिक नहीं देखा है, हालांकि - यह सुनिश्चित है कि अन्य विधि की अनुमति है।

1

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

3

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

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

+0

सहमत हुए। "रिलेशनशिप संचालित डिजाइन" यहां लागू होता है। – bishop

3

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

मैं एक उपयोगकर्ता तालिका, एक व्यक्ति तालिका बनाउंगा जिसमें उपयोगकर्ता के लिए एक शून्य विदेशी क्षेत्र है (यानी, व्यक्ति उपयोगकर्ता हो सकता है, लेकिन उसे नहीं करना है)।
फिर मैं एक स्पेशलपर्सन टेबल बनाउंगा जो व्यक्ति तालिका से संबंधित किसी भी अतिरिक्त फ़ील्ड से संबंधित है। यदि किसी दिए गए व्यक्ति के लिए स्पेशलपर्सन में एक रिकॉर्ड मौजूद है। आईडी, वह/यह एक विशेष व्यक्ति है।

5

क्या मैं यहाँ कहने जा रहा हूँ चला जाता है डेटाबेस आर्किटेक्ट भेजने के लिए conniptions में जा रहा है, लेकिन यहाँ:

एक अंतरफलक परिभाषा के बराबर के रूप में एक डेटाबेस दृश्य पर विचार करें। और एक तालिका कक्षा के बराबर है।

तो आपके उदाहरण में, सभी 3 व्यक्ति वर्ग आईपीएससन इंटरफ़ेस को लागू करेंगे। तो आपके पास 3 टेबल हैं - प्रत्येक 'उपयोगकर्ता', 'व्यक्ति' और 'स्पेशलपर्सन' के लिए एक।

फिर एक दृश्य 'PersonView' या जो कुछ भी सामान्य गुणों को चुनता है (जैसा कि आपके 'इंटरफेस' द्वारा परिभाषित किया गया है) सभी 3 टेबलों से एकल दृश्य में। संग्रहीत किए जा रहे व्यक्ति के वास्तविक प्रकार को संग्रहीत करने के लिए इस दृश्य में 'PersonType' कॉलम का उपयोग करें।

तो जब आप कोई प्रश्न चला रहे हैं जिसे किसी भी प्रकार के व्यक्ति पर संचालित किया जा सकता है, तो बस व्यक्ति दृश्य दृश्य से पूछें।

3

एक संबंधित डेटाबेस में विरासत को संभालने के लिए तीन बुनियादी रणनीतियों और आपकी सटीक आवश्यकताओं के आधार पर कई जटिल/bespoke विकल्प हैं।

  • तालिका प्रति वर्ग पदानुक्रम। पूरे पदानुक्रम के लिए एक टेबल।
  • प्रति उपखंड तालिका। सबक्साइड टेबल के बीच 0-1 एसोसिएशन के साथ प्रत्येक उप वर्ग के लिए एक अलग तालिका बनाई जाती है।
  • प्रति ठोस वर्ग तालिका। प्रत्येक कंक्रीट वर्ग के लिए एक एकल टेबल बनाई जाती है। हालांकि मेरी निजी preferance जब तक वहाँ एक विशिष्ट प्रदर्शन या संरचनात्मक कारण नहीं है में से एक के साथ जाने के उपवर्ग प्रति तालिका का उपयोग करने के लिए है
इन appoaches की

प्रत्येक, सामान्य, डेटा का उपयोग कोड, और डेटा भंडारण के बारे में अपने स्वयं के मुद्दों को उठाती है विकल्प

2

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

इस तरह से ऐसा करने का मुख्य कारण यह है कि यह अधिक तर्कसंगत रूप से सुसंगत हो जाता है और आप उन विशेष क्षेत्रों के साथ समाप्त नहीं होते हैं जो उस विशेष रिकॉर्ड के लिए नल और बकवास हैं। जब आप अपनी डिज़ाइन प्रक्रिया को पुन: सक्रिय करते हैं तो यह विधि उपप्रकारों में अतिरिक्त फ़ील्ड जोड़ने के लिए और अधिक आसान बनाती है।

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

तो मेरी डिजाइन किया जाएगा की तरह

PERSON (personid, नाम, पता, फोन, ...)

SPECIALPERSON कुछ (personid दें संदर्भ व्यक्ति (personid), अतिरिक्त क्षेत्रों ...)

उपयोगकर्ता (personid दें संदर्भ व्यक्ति (personid), उपयोगकर्ता नाम, encryptedpassword, अतिरिक्त क्षेत्रों ...)

तुम भी बाद में उस पर दृश्य बना सकते हैं, महाप्रकार और उप-प्रकार को एकत्रित करती है कि यदि आवश्यक है।

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

5

यह ओपी क्या नहीं पूछ सकता था, लेकिन मैंने सोचा कि मैं इसे यहां फेंक सकता हूं।

मुझे हाल ही में एक परियोजना में डीबी पॉलिमॉर्फिज्म का एक अनूठा मामला था। हमारे पास 60 से 120 संभव वर्गों के बीच था, प्रत्येक के अपने 30 से 40 अद्वितीय गुणों के सेट के साथ, और सभी कक्षाओं में लगभग 10-12 सामान्य गुण। हमने एसक्यूएल-एक्सएमएल रूट जाने का फैसला किया और एक ही टेबल के साथ समाप्त हो गया। कुछ ऐसा:

PERSON (personid,persontype, name,address, phone, XMLOtherProperties) 

कॉलम के रूप में सभी सामान्य गुणों और फिर एक बड़ा एक्सएमएल संपत्ति बैग शामिल है। ORM परत तब XMLOtherProperties से संबंधित गुणों को पढ़ने/लिखने के लिए ज़िम्मेदार थी। जैसा है:

public string StrangeProperty 
{ 
get { return XMLPropertyBag["StrangeProperty"];} 
set { XMLPropertyBag["StrangeProperty"]= value;} 
} 

(हम एक Hastable बजाय एक एक्सएमएल दस्तावेज़ के रूप में xml स्तंभ के मानचित्रण के साथ समाप्त हो गया है, लेकिन आप उपयोग कर सकते हैं जो कुछ भी सबसे अच्छा आपके दाल सूट)

यह किसी भी डिजाइन पुरस्कार जीतने के लिए नहीं जा रहा है , लेकिन यदि आपके पास संभावित कक्षाओं की बड़ी (या अज्ञात) संख्या है तो यह काम करेगा। और SQL2005 में आप अभी भी XPATH अपने एसक्यूएल प्रश्नों में कुछ संपत्ति के आधार पर पंक्तियों कि XML के रूप में संग्रहीत किया जाता है का चयन करने के .. उपयोग कर सकते हैं उस में लेने के लिए एक छोटा सा प्रदर्शन दंड है

38

मार्टिन फाउलर की Patterns of Enterprise Application Architecture पर एक नजर डालें।:

  • Single Table Inheritance:

    एक संबंधपरक डेटाबेस के लिए मानचित्रण, हम मिलती है कि जल्दी माउंट कर सकते हैं जब कई तालिकाओं में एक विरासत संरचना प्रसंस्करण को कम करने का प्रयास करते हैं। सिंगल टेबल विरासत एक विरासत संरचना के सभी वर्गों के सभी क्षेत्रों को एक ही तालिका में मानचित्रित करता है।

  • Class Table Inheritance:

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

  • Concrete Table Inheritance: देखने का एक वस्तु दृष्टान्त बिंदु से टेबल के

    सोच, एक समझदार मार्ग स्मृति में प्रत्येक वस्तु लेने के लिए और एक एकल डाटाबेस पंक्ति से मैप किया जा सके। यह कंक्रीट टेबल विरासत का तात्पर्य है, जहां विरासत पदानुक्रम में प्रत्येक ठोस वर्ग के लिए एक टेबल है।

2

हमारी कंपनी में हम एक मेज और अपने सबसे बुरे और कोई रेफेरेंन्शिअल सत्यनिष्ठा लागू किया जा सकता है और बहुत समझना मुश्किल मॉडल में सभी क्षेत्रों के संयोजन के द्वारा बहुरूपता के साथ सौदा। मैं निश्चित रूप से उस दृष्टिकोण के खिलाफ सिफारिश करेंगे।

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

1

यह एक पुरानी पोस्ट है, लेकिन मैंने सोचा कि मैं एक वैचारिक, प्रक्रियात्मक और प्रदर्शन दृष्टिकोण से वजन करूंगा।

पहला सवाल मैं पूछता हूं कि व्यक्ति, विशेषज्ञ और उपयोगकर्ता के बीच संबंध है, और चाहे किसी के लिए दोनों एक विशेषज्ञ और उपयोगकर्ता एक साथ हो। या, 4 संभावित संयोजनों में से कोई भी (कक्षा ए + बी, कक्षा बी + सी, कक्षा ए + सी, या एक + बी + सी)। यदि यह वर्ग type फ़ील्ड में मान के रूप में संग्रहीत है और इसलिए इन संयोजनों को ध्वस्त कर देगा, और वह पतन अस्वीकार्य है, तो मुझे लगता है कि एक से अधिक रिश्ते के लिए एक द्वितीयक तालिका की आवश्यकता होगी। मैंने सीखा है कि जब तक आप उपयोग का मूल्यांकन नहीं करते हैं और अपनी संयोजन जानकारी खोने की लागत का मूल्यांकन नहीं करते हैं।

अन्य कारक जो मुझे एक टेबल की तरफ झुकता है, वह परिदृश्य का आपका विवरण है। User उपयोगकर्ता नाम के साथ एकमात्र इकाई है (वर्कर (30) कहें) और पासवर्ड (वर्कर (32) कहें)। यदि सामान्य फ़ील्ड की संभावित लंबाई 20 फ़ील्ड प्रति औसत 20 वर्ण है, तो आपके कॉलम आकार में वृद्धि 62 से अधिक 62 है, या लगभग 15% - 10 साल पहले यह आधुनिक आरडीबीएमएस सिस्टम के साथ अधिक महंगी होती, खासकर एक क्षेत्र प्रकार जैसे वर्चर (उदाहरण के लिए MySQL) उपलब्ध है।

और, यदि सुरक्षा आपके लिए चिंता का विषय है, तो credentials (user_id, username, password) नामक माध्यमिक एक-से-एक तालिका होना फायदेमंद हो सकता है। इस तालिका को लॉगिन के समय पर प्रासंगिक रूप से जॉइन में शामिल किया जाएगा, लेकिन मुख्य तालिका में केवल "किसी भी" से संरचनात्मक रूप से अलग होगा। और, LEFT JOIN उन प्रश्नों के लिए उपलब्ध है जो "पंजीकृत उपयोगकर्ता" पर विचार करना चाहेंगे।

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

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