7

मैं फ्लुएंट एनएचबेर्नेट का उपयोग कर एएसपी.NET एमवीसी 3 एप्लिकेशन पर काम कर रहा हूं। मैं सिर्फ स्ट्रक्चर मैप का उपयोग कर आईओसी कंटेनर जोड़ने का प्रयास कर रहा हूं।संरचना मैप, एनएचबेर्नेट और एकाधिक डेटाबेस

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

internal class NHibernateRegistry : Registry 
{ 
    public NHibernateRegistry() 
    { 
     var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString; 

     For<ISessionFactory>() 
       .Singleton() 
       .Use(x => new AppSessionFactory().GetSessionFactory(connectionString)); 

     For<ISession>() 
      .HybridHttpOrThreadLocalScoped() 
      .Use(x => x.GetInstance<ISessionFactory>().OpenSession()); 
    } 

} 

public class AppSessionFactory 
{ 
    public ISessionFactory GetSessionFactory(string connectionString) 
    { 
     return GetConfig(connectionString) 
       .BuildSessionFactory(); 
    } 

    public static FluentConfiguration GetConfig(string connectionString) 
    { 
     return Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString))) 
      .Mappings(
       x => x.FluentMappings.AddFromAssemblyOf<AppEntity>()); 
    } 
} 

यह सब एक एकल डाटाबेस और ही सत्र कारखाने के लिए ठीक काम करता है:

मेरी StructureMap NHibernate रजिस्ट्री के लिए मैं निम्नलिखित है। हालांकि एप्लिकेशन एकाधिक डेटाबेस का उपयोग करता है।

इसे संभालने का सबसे अच्छा तरीका क्या है?

उत्तर

9

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

<connectionStrings> 
    <add name="LabX" connectionString="Data Source=labx;User ID=someuser;Password=somepassword"/> 
    <add name="LabY" connectionString="Data Source=laby;User ID=someuser;Password=somepassword"/> 
    <add name="BlackMesa" connectionString="Data Source=blackmesa;User ID=freemang;Password=crowbar"/> 
</connectionStrings> 

इस प्रकार, हम प्रत्येक कनेक्शन स्ट्रिंग के लिए एक अनूठा सत्र कारखाने की आवश्यकता है: यहाँ एक नमूना ConnectionStrings अनुभाग है। चलो एक NamedSessionFactory कि ISessionFactory लपेटता बनाएँ:

public interface INamedSessionFactory 
{ 
    public string Name { get; } // The name from the config file (e.g. "BlackMesa") 
    public ISessionFactory SessionFactory { get; } 
} 

public class NamedSessionFactory : INamedSessionFactory 
{ 
    public string Name { get; private set; } 
    public ISessionFactory SessionFactory { get; private set; } 

    public NamedSessionFactory(string name, ISessionFactory sessionFactory) 
    { 
     Name = name; 
     SessionFactory = sessionFactory; 
    } 
} 

अब हम अपने AppSessionFactory थोड़ा संशोधित करने की आवश्यकता। सबसे पहले, जो आपने बनाया है वह एक सत्र फैक्ट्री फैक्ट्री है - यह वह नहीं है जिसे हम ढूंढ रहे हैं। हम अपने फैक्ट्री को एक स्थान देना चाहते हैं और सत्र सत्र नहीं लेना चाहते हैं। Fluent NHibernate हमें सत्र कारखानों देता है।

public interface IAppSessionFactory 
{ 
    ISession GetSessionForLocation(string locationKey); 
} 

यहाँ चाल निर्माता में INamedSessionFactory वस्तुओं की एक सूची को स्वीकार है। स्ट्रक्चर मैप हमें उन सभी INMESessionFactory ऑब्जेक्ट्स को देना चाहिए जिन्हें हमने पंजीकृत किया है। हम एक सेकंड में पंजीकरण करेंगे।

public class AppSessionFactory : IAppSessionFactory 
{ 
    private readonly IList<INamedSessionFactory> _factories; 

    public AppSessionFactory(IEnumerable<INamedSessionFactory factories) 
    { 
     _factories = new List<INamedSessionFactory>(factories); 
    } 

यह वह जगह है जहां जादू होता है। एक स्थान कुंजी को देखते हुए, हम कारखानों की हमारी सूची के माध्यम से एक ही नाम के साथ एक स्थान की तलाश करते हैं, फिर उसे एक सत्र खोलने और कॉलर पर वापस करने के लिए कहें।

public ISession GetSessionForLocation(string locationKey) 
    { 
     var sessionFactory = _factories.Where(x => x.Name == locationKey).Single(); 

     return sessionFactory.OpenSession(); 
    } 
} 

अब हम सभी को एक साथ तार दें।

internal class NHibernateRegistry : Registry 
{ 
    public NHibernateRegistry() 
    { 

हम अपने app.config फ़ाइल में कनेक्शन तार के सभी के माध्यम से लूप करने जा रहे हैं (वहाँ इस उदाहरण में उनमें से तीन हो जाएगा) और हर एक के लिए एक INamedSessionFactory वस्तु रजिस्टर।

 foreach (ConnectionStringSettings location in ConfigurationManager.ConnectionStrings) 
     { 
      For<INamedSessionFactory>() 
       .Singleton() 
       .Use(x => new NamedSessionFactory(
        location.Name, 
        GetSessionFactory(location.ConnectionString)); 
     } 

हमें IAppSessionFactory पंजीकृत करने की भी आवश्यकता है।

 For<IAppSessionFactory>() 
      .Singleton() 
      .Use<AppSessionFactory>(); 
    } 

आप देखेंगे कि हमने कारखाने वर्ग से इस तर्क को स्थानांतरित कर दिया है ...फ्लुएंट एनएचबेर्नेट से सत्र कारखानों के निर्माण के लिए ये सहायक तरीके हैं।

private static ISessionFactory GetSessionFactory(string connectionString) 
    { 
     return GetConfig(connectionString) 
       .BuildSessionFactory(); 
    } 

    public static FluentConfiguration GetConfig(string connectionString) 
    { 
     return Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString))) 
      .Mappings(
       x => x.FluentMappings.AddFromAssemblyOf<AppEntity>()); 
    } 
} 

ऐसा करना चाहिए! चलो हमारे नमूने में प्राप्त करने के लिए भंडार बनाते हैं ...

public class SampleRepository 
{ 
    private readonly IAppSessionFactory _factory; 

    public SampleRepository(IAppSessionFactory factory) 
    { 
     _factory = factory; 
    } 

    public IEnumerable<Sample> GetSamplesForLocation(Location location) 
    { 
     using (ISession session = _factory.GetSessionForLocation(location.Key) 
     { 
      foreach (Sample sample in session.Query<Sample>()) 
       yield return sample; 
     } 
    } 
} 

अब आप SampleRepository का एक उदाहरण हो और तीन डेटाबेस हम app.config में पंजीकृत किया है में से किसी से नमूने को खींचने के लिए GetSamplesForLocation विधि का उपयोग कर सकते हैं। हालांकि ब्लैकमेसा से बचना चाहते हैं। मैं समझता हूं कि वहां समस्याएं थीं।

+0

मैं शायद ध्यान देना चाहिए कि यह साल हो गया है के बाद से मैं StructureMap या NHibernate का उपयोग किया है - तो मैं वहाँ कुछ खराब कर दिया हो सकता है। लेकिन मूल पैटर्न ध्वनि होना चाहिए। आशा करता हूँ की ये काम करेगा! –

+0

एक वास्तव में उपयोगी जवाब। मैं वर्तमान में StAcutreMap के TheInstanceNamed() को DAO को सत्र फ़ैक्टरीज़ असाइन करने के लिए उपयोग कर रहा हूं, जो ठीक काम करता प्रतीत होता है। मेरे पास कुछ समय अतिरिक्त समय होने पर आपके सुझावों को लागू करने के लिए देखेंगे। धन्यवाद। – TonE

0

क्या आप वाकई यह काम काम करते हैं? स्ट्रिंग ISessionFactory

public string ISessionFactory SessionFactory { get; private set; } 

इस होना चाहिए

public interface INamedSessionFactory 
{ 
    ISessionFactory SessionFactory { get; set; } 
    string Name { get; } 
} 

public class NamedSessionFactory : INamedSessionFactory 
{ 
    public ISessionFactory SessionFactory { get; set; } 
    public string Name { get; private set; } 

    public NamedSessionFactory(string Name, ISessionFactory SessionFactory) 
    { 
     this.Name = Name; 
     this.SessionFactory = SessionFactory; 
    } 
} 
संबंधित मुद्दे