एंटिटी फ्रेमवर्क: वन डाटाबेस, मल्टीपल डीबोनटेक्स। क्या यह एक बुरा विचार है? [बन्द है]


213

तिथि करने के लिए मेरी धारणा है कि एक DbContextआपके डेटाबेस का प्रतिनिधित्व करने के लिए है, और इस प्रकार, यदि आपका आवेदन एक डेटाबेस का उपयोग करता है, तो आप केवल एक ही चाहते हैं DbContext

हालांकि, कुछ सहकर्मी कार्यात्मक क्षेत्रों को अलग-अलग DbContextवर्गों में तोड़ना चाहते हैं।

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

तो मैं देख रहा हूँ:

ए) यह एक बुरा विचार क्यों हो सकता है के ठोस उदाहरण;

बी) का आश्वासन है कि यह सब ठीक काम करेगा।


जवाबों:


168

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

समस्या तब है जब आप अपने डेटाबेस को बनाने के लिए पहले कोड का उपयोग करना चाहते हैं - आपके आवेदन में केवल एक ही संदर्भ ऐसा कर सकता है। इसके लिए ट्रिक आमतौर पर एक अतिरिक्त संदर्भ है जिसमें आपकी सभी इकाइयां होती हैं जो केवल डेटाबेस निर्माण के लिए उपयोग की जाती हैं। आपके वास्तविक एप्लिकेशन संदर्भों में आपकी संस्थाओं के केवल सबसेट वाले डेटाबेस में डेटाबेस इनिशियलाइज़र सेट होना चाहिए।

ऐसे कई मुद्दे हैं जो आप कई संदर्भ प्रकारों का उपयोग करते समय देखेंगे - उदाहरण के लिए साझा इकाई प्रकार और उनका एक संदर्भ से दूसरे संदर्भ में गुजरना, आदि। आमतौर पर यह संभव है, यह आपके डिज़ाइन को बहुत अधिक क्लीनर और अलग-अलग कार्यात्मक क्षेत्रों को अलग कर सकता है, लेकिन इसके पास यह है अतिरिक्त जटिलता में लागत।


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

7
चूँकि मैं प्लुरलिटी की सदस्यता नहीं लेता हूँ, मुझे यह क्यू / ए के बाद अच्छी तरह से लिखा जूली लर्मन ( उसकी टिप्पणी ) का यह भयानक लेख मिला , लेकिन बहुत उपयुक्त: msdn.microsoft.com/en-us/magazine/jj883952.aspx
डेव टी।

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

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

9
@PiotrKwiatek यकीन नहीं है कि अगर यह आपकी टिप्पणी और अब के बीच बदल गया, लेकिन Enable-Migrations -ContextTypeName MyContext -MigrationsDirectory Migrations\MyContextMigrationsअब काम करता है।
ज़ैक

60

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

मैं अपने वोट का बैकअप लेने के लिए वास्तविक दुनिया के अनुभव के साथ, इस विचार के खिलाफ जाऊंगा।

मुझे एक बड़े एप्लिकेशन पर लाया गया था जिसमें एक ही डेटाबेस के लिए पांच संदर्भ थे। अंत में, हमने एक संदर्भ को छोड़कर सभी संदर्भों को हटा दिया - एक ही संदर्भ में वापस लौटना।

पहले कई संदर्भों का विचार एक अच्छा विचार लगता है। हम अपने डेटा एक्सेस को डोमेन में अलग कर सकते हैं और कई स्वच्छ हल्के संदर्भ प्रदान कर सकते हैं। डीडीडी की तरह लगता है, है ना? यह हमारे डेटा एक्सेस को सरल करेगा। एक और तर्क प्रदर्शन के लिए है कि हम केवल उस संदर्भ तक पहुंचते हैं जो हमें चाहिए।

लेकिन व्यवहार में, जैसे-जैसे हमारा आवेदन बढ़ता गया, हमारी कई तालिकाओं ने हमारे विभिन्न संदर्भों में रिश्तों को साझा किया। उदाहरण के लिए, संदर्भ 1 में तालिका ए के लिए प्रश्न भी संदर्भ 2 में तालिका बी में शामिल होने की आवश्यकता है।

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

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

अंत में, अच्छी खबर यह है कि कई संदर्भों को अलग करना आसान था। संदर्भ एक हल्के वस्तु होने का इरादा है। इसलिए मुझे नहीं लगता कि प्रदर्शन कई संदर्भों के लिए एक अच्छा तर्क है। लगभग सभी मामलों में, मेरा मानना ​​है कि एक एकल संदर्भ सरल, कम जटिल है, और संभवतः बेहतर प्रदर्शन करेगा, और आपको इसे काम करने के लिए काम-के बारे में एक गुच्छा लागू नहीं करना होगा।

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

सूक्ष्म सेवाओं के संबंध में, एक एकल संदर्भ अभी भी समझ में आता है। हालाँकि, सूक्ष्म सेवाओं के लिए, प्रत्येक सेवा का अपना संदर्भ होता है जिसमें केवल उस सेवा से संबंधित डेटाबेस तालिकाएँ शामिल होती हैं। दूसरे शब्दों में, यदि सेवा x तालिकाओं 1 और 2 तक पहुंचता है, और सेवा y तालिकाओं 3 और 4 तक पहुंचती है, तो प्रत्येक सेवा का अपना विशिष्ट संदर्भ होगा, जिसमें उस सेवा के लिए विशिष्ट सारणी शामिल हैं।

मुझे आपके विचारों में दिलचस्पी है।


8
मुझे यहां सहमत होना होगा, खासकर जब मौजूदा डेटाबेस को लक्षित करना। मैं अभी इस समस्या पर काम कर रहा हूं, और मेरी अब तक की भावना यह है: 1. कई संदर्भों में एक ही भौतिक तालिका का होना एक बुरा विचार है। 2. अगर हम यह तय नहीं कर सकते हैं कि एक तालिका एक संदर्भ या किसी अन्य की है, तो दो संदर्भों को तार्किक रूप से अलग होने के लिए पर्याप्त नहीं है।
जकरक

3
मैं यह तर्क दूंगा कि, CQRS करते समय, आपके पास संदर्भों के बीच कोई संबंध नहीं होगा (प्रत्येक दृश्य का अपना संदर्भ हो सकता है) इसलिए यह चेतावनी हर मामले पर लागू नहीं होती है जब कोई एकाधिक संदर्भों को प्राप्त करना चाहता हो। शामिल होने और संदर्भित करने के बजाय, प्रत्येक संदर्भ के लिए डेटा-डुप्लीकेशन का उपयोग करें। - हालांकि यह इस जवाब की उपयोगिता को नकारता नहीं है :)
शहरी

1
मुझे लगा कि तुम गहरे में दर्द का सामना करना पड़ा! : / मुझे भी लगता है कि एक संदर्भ सादगी के लिए बेहतर विकल्प है।
आह्मट

1
के खिलाफ मेरा एकमात्र तर्क, यह देखते हुए कि मैं अन्यथा पूरी तरह से सहमत हूं, पहचान के संबंध में है। विशेष रूप से क्षैतिज स्केलिंग के साथ, पहचान परत को लगभग सभी मामलों में अलग करना पड़ता है जहां लोड संतुलन पेश किया जाता है। कम से कम, कि मुझे क्या मिल रहा है।
बैरी

5
मेरे लिए ऐसा लगता है कि आप सभी तरह से डीडीडी नहीं गए, यदि आपके समुच्चय को अन्य समुच्चय जानने की जरूरत है। यदि आपको कुछ संदर्भ देने की आवश्यकता है, तो दो कारण हैं: वे एक ही समग्र विच में हैं इसका मतलब है कि उन्हें एक ही लेन-देन में बदलना होगा या वे नहीं हैं और आपको अपनी सीमा गलत मिली है।
सिमंस0n

54

यह धागा सिर्फ StackOverflow पर बुदबुदाया और इसलिए मैं एक और "बी) आश्वासन देना चाहता था कि यह सब ठीक होगा" :)

मैं डीडीडी बाउंडेड कॉन्टेक्स्ट पैटर्न के माध्यम से ठीक यही कर रहा हूं। मैंने अपनी पुस्तक, प्रोग्रामिंग एंटिटी फ्रेमवर्क: DbContext में इसके बारे में लिखा है और यह प्लुरलसाइट पर मेरे एक पाठ्यक्रम के भीतर 50 मिनट के मॉड्यूल का फोकस है -> http://pluralsight.com/training/Courses/tableOfContents/efaltecture


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

5
मैं बड़ी तस्वीर के लिए लक्ष्य कर रहा था। बिग एप्स में पुन: नगेट पैकेज के मुद्दे एक वीडियो के संदर्भ में बहुत सुंदर हैं। पुनः "टूट" उदाहरण ... हुह? हो सकता है कि इस कोर्स के लिए मेरे पाठ्यक्रम के बहुत महत्वपूर्ण होने के बाद से इसे निजी कॉनवो तक ले जाना बेहतर हो। मुझे लगता है कि SO आपको सीधे मुझसे संपर्क करने देता है।
जूली लर्मन

57
अच्छा होता कि जूली ओपी के मुद्दे / सवाल पर कुछ जानकारी साझा करती। इसके बजाय पद सिर्फ बहुवचन के लिए एक भुगतान सदस्यता को बढ़ावा देने के लिए है। यदि किसी उत्पाद के लिए प्लग, कम से कम सुझाए गए समाधान (डीडीडी बाउंडेड संदर्भ पैटर्न) पर जानकारी के लिए एक लिंक सहायक होगा। क्या "DDD 'को" प्रोग्रामिंग एंटिटी फ्रेमवर्क: DBContext "के पृष्ठ 22 पर वर्णित किया गया है? क्योंकि मैंने 'DDD' या 'बाउंडेड कॉनटेक्स्ट' के लिए कोई इंडेक्स (कोई इंडेक्स) नहीं देखा था, और वह ढूँढ नहीं सकता ... EF6 के लिए नए संशोधन करने के लिए आपका इंतजार नहीं कर सकता ...
Compassionate Narcissist

12
क्षमा करें, मैं बढ़ावा देने की कोशिश नहीं कर रहा था, सिर्फ ओपी से "आश्वासन चाहते हैं" को जोड़कर। लदिस्लाव और अन्य लोगों ने विवरण के साथ बहुत अच्छा काम किया। इसलिए मैं अभी कुछ ऐसा करने की कोशिश कर रहा था जो मैंने पहले ही बना लिया है जो कि एसओ पर संभवतः जितना रिले कर सकता है, उससे कहीं अधिक गहराई में जाता है। यहां अन्य संसाधन हैं, जहां मैंने कुछ सामान इंडिपेंड को कवर किया है: msdn.microsoft.com/en-us/magazine/jj883952.aspx & msdn.microsoft.com/en-us/magazine/dagou282868.aspx & oredev.org / 2013 / वेद-फ्र-कॉन्फ्रेंस /…
जूली लर्मन

@JulieLerman के कोड सुझावों का सारांश मेरा उत्तर देखें stackoverflow.com/a/36789520/1586498
Ozbus

46

डिफ़ॉल्ट स्कीमा सेट करके संदर्भों को भेद करना

EF6 में आपके पास कई संदर्भ हो सकते हैं, बस OnModelCreatingआपके द्वारा DbContextव्युत्पन्न वर्ग (जहां धाराप्रवाह-एपीआई कॉन्फ़िगरेशन है) की विधि में डिफ़ॉल्ट डेटाबेस स्कीमा के लिए नाम निर्दिष्ट करें । यह EF6 में काम करेगा:

public partial class CustomerModel : DbContext
{   
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("Customer");

        // Fluent API configuration
    }   
}

यह उदाहरण आपके डेटाबेस तालिकाओं ("dbo" के बजाय) के रूप में "ग्राहक" का उपयोग करेगा। इससे भी महत्वपूर्ण बात यह है कि यह __MigrationHistoryतालिका (नों) को भी उपसर्ग करेगा , उदाहरण के लिए Customer.__MigrationHistory। तो आप __MigrationHistoryएक डेटाबेस में एक से अधिक टेबल रख सकते हैं , प्रत्येक संदर्भ के लिए। इसलिए आप एक संदर्भ के लिए जो बदलाव करते हैं, वह दूसरे के साथ गड़बड़ नहीं करेगा।

माइग्रेशन जोड़ते समय, कमांड DbMigrationsConfigurationमें पैरामीटर के रूप में अपने कॉन्फ़िगरेशन वर्ग (व्युत्पन्न ) से पूरी तरह से योग्य नाम निर्दिष्ट करें add-migration:

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


संदर्भ कुंजी पर एक छोटा शब्द

इस MSDN लेख के अनुसार " अध्याय - एक ही डेटाबेस को लक्षित करने वाले कई मॉडल " EF 6 शायद स्थिति को संभाल लेंगे भले ही केवल एक MigrationHistoryतालिका मौजूद हो, क्योंकि तालिका में माइग्रेशन को अलग करने के लिए एक ContextKey कॉलम है।

हालाँकि, मैं MigrationHistoryऊपर बताए गए जैसे डिफ़ॉल्ट स्कीमा को निर्दिष्ट करके एक से अधिक तालिका रखना पसंद करता हूं ।


अलग माइग्रेशन फ़ोल्डर का उपयोग करना

ऐसे परिदृश्य में आप अपने प्रोजेक्ट में विभिन्न "माइग्रेशन" फ़ोल्डरों के साथ काम करना चाहते हैं। आप संपत्ति DbMigrationsConfigurationका उपयोग करके अपने व्युत्पन्न वर्ग को सेट कर सकते MigrationsDirectoryहैं:

internal sealed class ConfigurationA : DbMigrationsConfiguration<ModelA>
{
    public ConfigurationA()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelA";
    }
}

internal sealed class ConfigurationB : DbMigrationsConfiguration<ModelB>
{
    public ConfigurationB()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelB";
    }
}


सारांश

सब सब में, आप कह सकते हैं कि सब कुछ साफ-साफ अलग हो गया है: प्रोजेक्ट में कॉन्टेक्ट्स, माइग्रेशन फ़ोल्डर और डेटाबेस में टेबल।

मैं इस तरह के समाधान का चयन करूंगा, अगर संस्थाओं के समूह हैं जो एक बड़े विषय का हिस्सा हैं, लेकिन एक दूसरे से (विदेशी कुंजी के माध्यम से) संबंधित नहीं हैं।

यदि संस्थाओं के समूहों के पास ऐसा करने के लिए कुछ भी नहीं है, तो मैं उनमें से प्रत्येक के लिए एक अलग डेटाबेस बनाऊंगा और उन्हें अलग-अलग परियोजनाओं में एक्सेस कर सकता हूं, शायद प्रत्येक प्रोजेक्ट में एक ही संदर्भ के साथ।


जब आप 2 संस्थाओं को अलग-अलग संदर्भों में अद्यतन करने की आवश्यकता है, तो आप क्या करते हैं?
sotn

मैं एक नया (सेवा) वर्ग बनाऊंगा जो दोनों संदर्भों को जानता हो, एक अच्छा नाम और इस वर्ग की जिम्मेदारियों के बारे में सोचता हो और इस अद्यतन को अपने तरीकों में से एक करता हो।
मार्टिन

7

नीचे प्राप्त करने के लिए सरल उदाहरण:

    ApplicationDbContext forumDB = new ApplicationDbContext();
    MonitorDbContext monitor = new MonitorDbContext();

मुख्य संदर्भ में बस गुणों को सीमित करें: (डीबी बनाने और बनाए रखने के लिए उपयोग किया जाता है) नोट: बस संरक्षित उपयोग करें: (इकाई का खुलासा नहीं हुआ है)

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("QAForum", throwIfV1Schema: false)
    {

    }
    protected DbSet<Diagnostic> Diagnostics { get; set; }
    public DbSet<Forum> Forums { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Thread> Threads { get; set; }
    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

मॉनिटरकॉन्टेक्स: यहां अलग एंटिटी का खुलासा करें

public class MonitorDbContext: DbContext
{
    public MonitorDbContext()
        : base("QAForum")
    {

    }
    public DbSet<Diagnostic> Diagnostics { get; set; }
    // add more here
}

निदान मॉडल:

public class Diagnostic
{
    [Key]
    public Guid DiagnosticID { get; set; }
    public string ApplicationName { get; set; }
    public DateTime DiagnosticTime { get; set; }
    public string Data { get; set; }
}

यदि आप चाहें, तो आप मुख्य ApplicationDbContext के अंदर सभी संस्थाओं को चिह्नित कर सकते हैं, तो स्कीमा के प्रत्येक पृथक्करण के लिए आवश्यकतानुसार अतिरिक्त संदर्भ बनाएँ।

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


2
इससे काफी मदद मिली। "माध्यमिक" संदर्भ को साझा तालिका घोषित करने की आवश्यकता नहीं है। बस इसे मैन्युअल रूप से जोड़ें DbSet<x>परिभाषा है। मैं एक आंशिक वर्ग में मेल खाता हूँ जो EF डिज़ाइनर बनाता है।
ग्लेन लिटिल

आपने मुझे बहुत सिरदर्द से बचाया, सर! आपने स्वीकृत उत्तर के बजाय एक ठोस समाधान प्रदान किया। वास्तव में सराहनीय!
वूई

6

अनुस्मारक: यदि आप कई संदर्भों को जोड़ते हैं, तो सुनिश्चित करें कि आपने RealContexts.OnModelCreating()अपने एकल में सभी कार्यक्षमता को n पेस्ट में कटौती की है CombinedContext.OnModelCreating()

मैं सिर्फ समय बर्बाद कर रहा हूं कि मेरे कैस्केड डिलीट रिलेशनशिप को केवल इस बात के लिए संरक्षित नहीं किया जा रहा है कि मैंने modelBuilder.Entity<T>()....WillCascadeOnDelete();कोड को अपने वास्तविक संदर्भ से अपने संयुक्त संदर्भ में पोर्ट नहीं किया था ।


6
काटने और चिपकाने के बजाय, क्या आप सिर्फ OtherContext.OnModelCreating()अपने संयुक्त संदर्भ से कॉल कर सकते हैं ?
एलेक्सफॉक्सगिल

4

मेरे पेट ने मुझे वही बात बताई जब मैं इस डिज़ाइन के पार आया।

मैं एक कोड बेस पर काम कर रहा हूं, जहां एक डेटाबेस में तीन dbContexts हैं। 3 dbcontexts में से 2 1 dbcontext की जानकारी पर निर्भर हैं क्योंकि यह प्रशासनिक डेटा को कार्य करता है। इस डिज़ाइन ने इस बात पर अड़चनें पैदा की हैं कि आप अपने डेटा को कैसे क्वेरी कर सकते हैं। मैं इस समस्या में भाग गया जहाँ आप dbcontexts में शामिल नहीं हो सकते। इसके बजाय आपको जो करने की आवश्यकता होती है, वह दो अलग-अलग dbcontexts को क्वेरी करता है, फिर परिणाम के रूप में दो के संयोजन को प्राप्त करने के लिए दोनों के माध्यम से स्मृति या पुनरावृति में शामिल हों। इसके साथ समस्या यह है कि विशिष्ट परिणाम सेट के लिए क्वेरी करने के बजाय आप अब अपने सभी रिकॉर्ड्स को मेमोरी में लोड कर रहे हैं और फिर मेमोरी में दो परिणाम सेट के खिलाफ एक जॉइन कर रहे हैं। यह वास्तव में चीजों को धीमा कर सकता है।

मैं सवाल पूछूंगा "सिर्फ इसलिए कि तुम कर सकते हो, तुम चाहिए? "

इस डिज़ाइन से संबंधित समस्या के लिए इस लेख को देखें। निर्दिष्ट LINQ अभिव्यक्ति में विभिन्न संदर्भों से संबंधित प्रश्नों के संदर्भ हैं


3
मैंने एक बड़ी प्रणाली पर काम किया है जहां हमारे पास कई संदर्भ थे। एक चीज़ जो मुझे मिली वह यह थी कि कभी-कभी आपको एक ही DbSet को कई संदर्भों में शामिल करना पड़ता था। एक ओर यह कुछ शुद्धता चिंताओं को तोड़ता है, लेकिन यह आपको अपने प्रश्नों को पूरा करने की अनुमति देता है। ऐसे मामले के लिए जहां कुछ व्यवस्थापक तालिकाएं हैं जिन्हें आपको पढ़ने की आवश्यकता है, आप उन्हें आधार DbContext वर्ग में जोड़ सकते हैं और उन्हें अपने ऐप मॉड्यूल संदर्भों में इनहेरिट कर सकते हैं। आपको "वास्तविक" व्यवस्थापक संदर्भ के उद्देश्य को "व्यवस्थापक तालिकाओं के लिए रखरखाव प्रदान करने" के रूप में पुनर्परिभाषित किया जा सकता है, बजाय उन्हें सभी पहुंच प्रदान करने के।
JMarsch

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

1
आप दोनों में संस्थाओं को शामिल करने के लिए नहीं हैं, आप हमेशा आईडी प्राप्त कर सकते हैं और एक अलग संदर्भ में 2-क्वेरी कर सकते हैं। छोटे सिस्टम के लिए यह बुरा है, कई DBs के लिए / कई टेबल के कई देवता के साथ सिस्टम 2 प्रश्नों की तुलना में बहुत बड़ी और अधिक कठिन समस्या है।
user1496062

4

[@JulieLerman के DDD MSDN पत्रिका अनुच्छेद 2013] से प्रेरित [1]

    public class ShippingContext : BaseContext<ShippingContext>
{
  public DbSet<Shipment> Shipments { get; set; }
  public DbSet<Shipper> Shippers { get; set; }
  public DbSet<OrderShippingDetail> Order { get; set; } //Orders table
  public DbSet<ItemToBeShipped> ItemsToBeShipped { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    modelBuilder.Ignore<LineItem>();
    modelBuilder.Ignore<Order>();
    modelBuilder.Configurations.Add(new ShippingAddressMap());
  }
}

public class BaseContext<TContext>
  DbContext where TContext : DbContext
{
  static BaseContext()
  {
    Database.SetInitializer<TContext>(null);
  }
  protected BaseContext() : base("DPSalesDatabase")
  {}
}   

"यदि आप नया विकास कर रहे हैं और आप अपनी कक्षाओं के आधार पर अपने डेटाबेस का कोड बनाना या उसे पहले जाने देना चाहते हैं, तो आपको DbContext का उपयोग करके एक" uber-model "बनाने की आवश्यकता होगी जिसमें सभी वर्ग और संबंध शामिल हों एक पूर्ण मॉडल बनाएं जो डेटाबेस का प्रतिनिधित्व करता है। हालांकि, इस संदर्भ को बेसकॉन्टेक्स से विरासत में प्राप्त नहीं होना चाहिए। " जीएल


2

पहले कोड में, आपके पास कई DBContext और सिर्फ एक डेटाबेस हो सकता है। आपको बस कंस्ट्रक्टर में कनेक्शन स्ट्रिंग निर्दिष्ट करना होगा।

public class MovieDBContext : DbContext
{
    public MovieDBContext()
        : base("DefaultConnection")
    {

    }
    public DbSet<Movie> Movies { get; set; }
}

हाँ, आप कर सकते हैं, लेकिन आप अलग-अलग संस्थाओं से अलग-अलग db संदर्भों से कैसे क्वेरी कर सकते हैं?
रेजा

2

एक और बिट "ज्ञान"। मेरे पास एक डेटाबेस है जो इंटरनेट और आंतरिक ऐप दोनों का सामना कर रहा है। मेरे पास प्रत्येक चेहरे के लिए एक संदर्भ है। यह मुझे एक अनुशासित, सुरक्षित अलगाव रखने में मदद करता है।


1

मैं एक मामले को साझा करना चाहता हूं, जहां मुझे लगता है कि एक ही डेटाबेस में कई DBContexts होने की संभावना अच्छी समझ में आती है।

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

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


2
मैं अपने उत्तर में किसी भी प्रश्न को देखने में विफल हूं। मैं एक भी सवाल नहीं पूछ रहा हूँ! एक परिदृश्य साझा करने के बजाय जहां चर्चा का विषय अच्छा अर्थ रखता है।
प्रातः

0

हुह, प्रत्येक DB स्कीमा के लिए अलग-अलग DB संदर्भों के साथ एक समस्या पर काफी समय बिताया, आशा है कि यह किसी और की मदद करेगा ...

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

इन वस्तुओं को अलग से C # में लोड किया गया था, सबसे पहले, विषय को 1 संदर्भ से लोड किया गया था, फिर उपयोगकर्ताओं को अन्य आईडी संदर्भ से उपयोगकर्ता आईडी के माध्यम से लोड किया गया था - अच्छा नहीं है, इसे ठीक करना होगा! ( EF 6 के साथ एक ही डेटाबेस में कई dbcontexts का उपयोग करने के समान )

सबसे पहले, मैंने KB स्कीम में पहचान स्कीमा से KB स्कीमा, EF modelBuilder में गुम FK निर्देशों को जोड़ने का प्रयास किया। उसी तरह जैसे कि केवल 1 संदर्भ था, लेकिन मैंने इसे 2 तक अलग कर दिया।

modelBuilder.Entity<Topic>(entity =>
{
  entity.HasOne(d => d.Creator)
    .WithMany(p => p.TopicCreator)
    .HasForeignKey(d => d.CreatorId)
    .HasConstraintName("fk_topic_app_users");

यह काम नहीं किया, क्योंकि kb db संदर्भ में उपयोगकर्ता ऑब्जेक्ट के बारे में कोई जानकारी नहीं थी, पोस्टग्रेज त्रुटि वापस कर दिया relation "AppUsers" does not exist। चयनित कथन में स्कीमा, फ़ील्ड नाम आदि के बारे में उचित जानकारी नहीं है

मैंने लगभग हार मान ली, लेकिन फिर मैंने एक स्विच "-d" देखा जब दौड़ रहा था dotnet ef dbcontext scaffold। -डाटा-एनोटेशन के लिए इसका छोटा - मॉडल (जहां संभव हो) को कॉन्फ़िगर करने के लिए विशेषताओं का उपयोग करें। यदि छोड़ा गया है, तो केवल धाराप्रवाह एपीआई का उपयोग किया जाता है। निर्दिष्ट किए गए इस स्विच के साथ, ऑब्जेक्ट गुणों को डीबी संदर्भ में नहीं OnModelCreating(), बल्कि विशेषताओं के साथ ऑब्जेक्ट पर ही परिभाषित किया गया था।

इस तरह, ईएफ को उचित क्षेत्र के नाम और स्कीमा के साथ एक उचित एसक्यूएल बयान उत्पन्न करने के लिए पर्याप्त जानकारी मिली।

टीएल; डीआर: अलग-अलग डीबी संदर्भों को उनके बीच संबंधों (एफके) को अच्छी तरह से संभालना नहीं है, प्रत्येक संदर्भ में केवल अपनी संस्थाओं के बारे में जानकारी है। "-डेटा-एनोटेशन" स्विच को निर्दिष्ट करते समय dotnet ef dbcontext scaffold, ये संकेत प्रत्येक अलग संदर्भ में संग्रहीत होते हैं, लेकिन डीबी ऑब्जेक्ट्स पर स्वयं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.