2010-12-14 13 views
8

के साथ कई डेटाबेस प्रबंधित करना मैंने सोचा कि मुझे यह सवाल तब मिलेगा जब मैंने अपने समाधान पर नूडल किया था।NHibernate और Autofac

एक आवेदन के बड़े हिस्से को बनाने के बाद, मेरे पास एक अतिरिक्त डेटाबेस (2 कुल, कोई ज्ञात अन्य) को पढ़ने/लिखने का समर्थन करने के लिए आखिरी मिनट की आवश्यकता नहीं है। मैंने डीआई/आईओसी घटकों की आपूर्ति ऑटोफैक के साथ एनएचबीर्नेट का उपयोग करके आवेदन बनाया। एफडब्ल्यूआईडब्ल्यू, यह एक एएसपी.नेट एमवीसी 2 ऐप में रहता है।

मेरे पास एक सामान्य भंडार वर्ग है जो एनएचबीर्नेट सत्र लेता है। सैद्धांतिक रूप से, मैं इस जेनेरिक रिपोजिटरी (IRepository<>) का उपयोग दूसरे डेटाबेस के लिए तब तक जारी रख सकता हूं जब तक कि इसे पारित सत्र उचित सत्र फैक्ट्री से उत्पन्न होता है, है ना?

ठीक है, जब ऐप शुरू होता है, तो ऑटोफैक यह बात करता है। साथ सत्र और SessionFactory के संबंध में, मैं एक मॉड्यूल है जो यह बताता है:

builder.Register(c => c.Resolve<ISessionFactory>().OpenSession()) 
    .InstancePerMatchingLifetimeScope(WebLifetime.Request) 
    .OnActivated(e => 
    { 
     e.Context.Resolve<TransactionManager>().CurrentTransaction = ((ISession)e.Instance).BeginTransaction(); 
    }); 

builder.Register(c => ConfigureNHibernate()) 
    .SingleInstance(); 

जहां ConfigureNHibernate() है, जो आधार SessionFactory देता है, की तरह दिखता है:

private ISessionFactory ConfigureNHibernate() 
{ 
    Configuration cfg = new Configuration().Configure(); 
    cfg.AddAssembly(typeof(Entity).Assembly); 
    return cfg.Configure().BuildSessionFactory(); 
} 

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

इस तरह से किसी भी आईओसी कंटेनर और एनएचबीरनेट का उपयोग करते समय किसी को भी इस परिदृश्य का अनुभव होता है?

संपादित मैं एक GetSessionFactory विधि है कि एक विन्यास फाइल पथ लेता बाहर टोंटदार किया है, HttpRuntime.Cache में मेल खाने वाले SessionFactory के अस्तित्व के लिए जाँच, एक नया उदाहरण अगर एक पहले से ही मौजूद नहीं है बनाता है, और सत्र फैक्ट्री देता है। अब मुझे अभी भी ऑटोफैक को कैसे और कब उचित कॉन्फ़िगर पथ निर्दिष्ट करना है, यह बताने की आवश्यकता है। नई विधि की तरह (बिली के 2006 पद here से भारी उधार) दिखता है:

private ISessionFactory GetSessionFactory(string sessionFactoryConfigPath) 
    { 
     Configuration cfg = null; 
     var sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath); 

     if (sessionFactory == null) 
     { 
      if (!File.Exists(sessionFactoryConfigPath)) 
       throw new FileNotFoundException("The nhibernate configuration file at '" + sessionFactoryConfigPath + "' could not be found."); 

      cfg = new Configuration().Configure(sessionFactoryConfigPath); 
      sessionFactory = cfg.BuildSessionFactory(); 

      if (sessionFactory == null) 
      { 
       throw new Exception("cfg.BuildSessionFactory() returned null."); 
      } 

      HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null); 
     } 

     return sessionFactory; 
    } 
+1

कैश में सत्र फैक्ट्री संग्रहीत करना एक बुरा विचार है। यह ऐसा कुछ नहीं है जो सिर्फ गायब हो और फिर से बनाया जा सके। –

+0

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

उत्तर

11

मैं यह सोचते कर रहा हूँ कि आप संस्थाओं प्रत्येक डेटाबेस में जाने के लिए अलग-अलग प्रकार चाहते हैं; यदि आप प्रत्येक डेटाबेस में एक ही तरह की इकाइयां रखना चाहते हैं, तो AutofacContrib.Multitenant देखें।

दो तत्व है कि इस परिदृश्य के साथ मदद कर सकते हैं: इस पर

सबसे पहले, दो अलग-अलग डेटाबेस को संदर्भित करने के लिए नामित सेवाओं का उपयोग करें। मैं उन्हें "db1" और "db2 कहूंगा "।सत्र के लिए डेटाबेस से संबंधित है, नीचे से ऊपर तक के सभी घटकों, एक नाम के साथ पंजीकृत:

builder.Register(c => ConfigureDb1()) 
    .Named<ISessionFactory>("db1") 
    .SingleInstance(); 

builder.Register(c => c.ResolveNamed<ISessionFactory>("db1").OpenSession()) 
    .Named<ISession>("db1") 
    .InstancePerLifetimeScope(); 

// Same for "db2" and so-on. 

अब, यह सोचते हैं आप एक प्रकार NHibernateRepository<T> है कि इसके निर्माता पैरामीटर के रूप में एक ISession स्वीकार करता है, और है कि आप किसी इकाई के प्रकार को दिए जाने पर WhichDatabase(Type entityType) फ़ंक्शन लिख सकता है जो "db1" या "db2" देता है।

हम इकाई प्रकार के आधार पर सत्र को गतिशील रूप से चुनने के लिए ResolvedParameter का उपयोग करते हैं।

builder.RegisterGeneric(typeof(NHibernateRepository<>)) 
    .As(typeof(IRepository<>)) 
    .WithParameter(new ResolvedParameter(
     (pi, c) => pi.ParameterType == typeof(ISession), 
     (pi, c) => c.ResolveNamed<ISession>(
      WhichDatabase(pi.Member.DeclaringType.GetGenericArguments()[0]))); 

(चेतावनी - संकलित और गूगल क्रोम में परीक्षण किया;))

अब, को हल करने IRepository<MyEntity> उचित सत्र का चयन करेंगे, और सत्र lazily initialised किया जाना है और सही ढंग से Autofac द्वारा निपटारा जारी रहेगा।

आपको निश्चित रूप से लेनदेन प्रबंधन के बारे में सावधानी से सोचना होगा।

आशा है कि यह चाल है! एनबी

+1

दोस्त, वह था। इतना अद्भुत! मेरे परिदृश्य के लिए मुझे कुछ झुकाव था, और अद्यतन ऑटोफैक स्रोत में थोड़ा और खोला गया, इसलिए मुझे समझ में आया कि क्या हो रहा था, लेकिन नरक हाँ, यही कारण है कि मुझे एसओ पसंद है! धन्यवाद निकोलस! – nkirkes

+0

सुनने के लिए बहुत बढ़िया - आपका स्वागत है! –