Pensé que podría obtener esta pregunta mientras redactaba una solución por mi cuenta.Gestionando múltiples bases de datos con NHibernate y Autofac
Después de haber desarrollado la mayor parte de una aplicación, tengo un requisito de último minuto para admitir la lectura/escritura en una base de datos adicional (2 en total, sin conocer otras). Creé la aplicación usando NHibernate, con Autofac suministrando los componentes DI/IoC. FWIW, esto reside en una aplicación ASP.NET MVC 2.
Tengo una clase de repositorio genérico que toma una sesión de NHibernate. Teóricamente, puedo continuar usando este repositorio genérico (IRepository<>
) para la segunda base de datos siempre que la sesión que se pasa a ella se genere desde una SessionFactory apropiada, ¿verdad?
Bueno, cuando se inicia la aplicación, Autofac lo hace. En cuanto a la sesión y SessionFactory, tengo un módulo que establece:
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();
donde ConfigureNHibernate(), que devuelve el SessionFactory base, se ve así:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
Actualmente, esto está limitado a solo la única base de datos. En cualquier otro escenario de NHib, probablemente empujaría las instancias de SessionFactories por separado a un hash, y las recuperaría según fuera necesario. No quiero tener que volver a diseñar todo ya que estamos bastante cerca de un lanzamiento importante. Entonces, supongo que necesito modificar al menos los métodos anteriores para poder configurar de forma independiente dos SessionFactories. Mi área gris es cómo voy a especificar la fábrica correcta que se utilizará con un repositorio específico (o al menos para las entidades específicas de esa segunda base de datos).
¿Alguien tiene experiencia con este escenario mientras usa un contenedor de IoC y NHibernate de esta manera?
EDITAR He apagó un método GetSessionFactory que toma una ruta de archivo de configuración, comprueba la existencia de una SessionFactory coincidente en la HttpRuntime.Cache, crea una nueva instancia si uno no existe ya, y devuelve esa SessionFactory. Ahora todavía necesito explicar cómo decirle a Autofac cómo y cuándo especificar una ruta de configuración adecuada. El nuevo método se parece a (prestado en gran medida de la posterior a 2006 de 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;
}
Almacenar la fábrica de la sesión en el caché es una mala idea. No es algo que pueda desaparecer y ser recreado. –
Lo sé. En realidad, voy a tener que administrar la vida útil de ese objeto en caché. El ejemplo de Billy en realidad va un paso más allá y creó un producto único con ámbito de clase SessionManager que se ocupa de las preocupaciones de almacenamiento en caché. Yo estaba tratando de embrutecer por lo que podría finalmente dejar que Autofac administrarlo a través de él es poseer (muy elegante) mecanismos de ámbito. – nkirkes