Pomyślałem, że dostanę to pytanie, podczas gdy ja osobiście przygotowałem rozwiązanie.Zarządzanie wieloma bazami danych za pomocą NHibernate i Autofac
Po zbudowaniu większości aplikacji, mam w ostatniej chwili wymóg obsługi odczytu/zapisu do dodatkowej bazy danych (2 całkowite, nieznane inne). Zbudowałem aplikację przy pomocy NHibernate, a Autofac dostarcza komponenty DI/IoC. FWIW, to rezyduje w aplikacji ASP.NET MVC 2.
Mam ogólne klasy repozytorium, które ma sesję NHibernate. Teoretycznie mogę nadal używać tego ogólnego repozytorium (IRepository<>
) dla drugiej bazy danych, o ile sesja, która zostanie mu przekazana, zostanie utworzona z odpowiedniego SessionFactory, prawda?
Po uruchomieniu aplikacji Autofac robi to. W odniesieniu do sesji i SessionFactory, mam moduł, który stwierdza:
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();
gdzie ConfigureNHibernate(), która zwraca SessionFactory bazową, wygląda następująco:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
Obecnie ta jest ograniczona do zaledwie jedna baza danych. W każdym innym scenariuszu nibib, prawdopodobnie wepchnęłbym instancje oddzielnych SessionFactories w skrót, i odzyskałbym je w razie potrzeby. Nie chcę ponownie projektować całości, ponieważ jesteśmy blisko wydania głównego. Zgaduję, że muszę zmodyfikować przynajmniej powyższe metody, aby móc samodzielnie skonfigurować dwa SessionFactories. Mój szary obszar to sposób, w jaki określę poprawną fabrykę używaną z określonym repozytorium (lub przynajmniej dla jednostek właściwych dla tej drugiej bazy danych).
Ktoś ma doświadczenie w tym scenariuszu podczas korzystania z kontenera IoC i NHibernate w ten sposób?
EDIT mam zgaszone się GetSessionFactory metodę, która pobiera ścieżkę pliku konfiguracyjnego, czeki do istnienia z SessionFactory dopasowującego w HttpRuntime.Cache, tworzy nową instancję jeśli nie istnieje, a zwraca wartość SessionFactory. Teraz wciąż muszę zastanowić się, jak powiedzieć Autofac, jak i kiedy określić odpowiednią ścieżkę konfiguracji. Nowa metoda wygląda (pożyczył ciężko od Billy'ego 2006 postu 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;
}
Przechowywanie fabryki sesji w pamięci podręcznej to zły pomysł. To nie jest coś, co może zniknąć i zostać odtworzone. –
Wiem. W rzeczywistości będę musiał zarządzać czasem życia tego buforowanego obiektu. Przykład Billy'ego czyni to o krok dalej i tworzy singletonową klasę SessionManager, która zajmuje się problemami z buforowaniem. Próbowałem go zgubić, aby w końcu pozwolić Autofacowi zarządzać nim poprzez własne (bardzo eleganckie) mechanizmy scopingowe. – nkirkes