entity-framework - मन में गलत विचार आना




इकाई फ्रेमवर्क: एक डेटाबेस, एकाधिक डीबीकॉन्टेक्स। क्या यह एक बुरा विचार है? (8)

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

तो मैं ए के लिए देख रहा हूं) ठोस उदाहरण क्यों हो सकते हैं कि यह एक बुरा विचार हो सकता है, या बी) आश्वासन है कि यह सब ठीक काम करेगा।


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


[@ जुलीरमैन के डीडीडी एमएसडीएन मैग आर्टिकल 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")
  {}
}   

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


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

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

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


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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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


डिफ़ॉल्ट schmema सेट करके संदर्भों को distiguishing

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

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

        // Fluent API configuration
    }   
}

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

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

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


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

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

हालांकि मैं उपर्युक्त समझाया गया डिफ़ॉल्ट स्कीमा निर्दिष्ट करके एक से अधिक MigrationHistory तालिका को प्राथमिकता देना पसंद करता हूं।


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

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

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";
    }
}


सारांश

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

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

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





dbcontext