Ho pensato di ottenere questa domanda là fuori mentre ho snodato una soluzione per conto mio.Gestione di più database con NHibernate e Autofac
Dopo aver costruito la maggior parte della domanda, ho un requisito all'ultimo minuto per supportare la lettura/scrittura di un database aggiuntivo (2 totali, gli altri non sono noti). Ho creato l'applicazione utilizzando NHibernate, con Autofac che fornisce i componenti DI/IoC. FWIW, questo risiede in un'app ASP.NET MVC 2.
Ho una classe di repository generica che accetta una sessione di NHibernate. In teoria, posso continuare a utilizzare questo repository generico (IRepository<>
) per il secondo database fino a quando la sessione che viene passata ad esso viene generata da una SessionFactory appropriata, giusto?
Bene, quando l'app si avvia, Autofac fa la cosa. Per quanto riguarda la sessione e SessionFactory, ho un modulo che afferma:
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();
dove ConfigureNHibernate(), che restituisce il SessionFactory di base, si presenta come:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
Attualmente, questo è limitato al solo l'unico database. In qualsiasi altro scenario di NHib, probabilmente spingere le istanze delle SessionFactories separate in un hash e recuperarle quando necessario. Non voglio dover riprogettare l'intera faccenda dato che siamo abbastanza vicini a una major release. Quindi, suppongo di dover modificare almeno i metodi sopra in modo da poter configurare in modo indipendente due SessionFactories. La mia area grigia è come andrò a specificare la factory corretta da utilizzare con un repository specifico (o almeno per le entità specifiche del secondo database).
Qualcuno ha esperienza con questo scenario durante l'utilizzo di un contenitore CIO e NHibernate in questo modo?
EDIT ho spense un metodo GetSessionFactory che prende un percorso di file di configurazione, i controlli per l'esistenza di un SessionFactory corrispondente nel HttpRuntime.Cache, crea una nuova istanza se non ne esiste già, e restituisce SessionFactory. Ora ho ancora bisogno di capire come dire a Autofac come e quando specificare un percorso di configurazione appropriato. Il nuovo metodo si presenta come (preso in prestito pesantemente dal post 2006 Billy 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;
}
Memorizzare la memoria di sessione nella cache è una cattiva idea. Non è qualcosa che può semplicemente svanire e essere ricreato. –
Lo so. In realtà, dovrò gestire la durata di quell'oggetto memorizzato nella cache. L'esempio di Billy in realtà fa un ulteriore passo avanti e ha creato una classe SessionManager con ambito singleton che si occupa dei problemi di memorizzazione nella cache. Stavo cercando di ridurlo in modo che potessi finalmente lasciare che Autofac gestisse i suoi meccanismi di scopatura (molto eleganti). – nkirkes