Je pensais que j'aurais cette question là-bas pendant que je noodled sur une solution par moi-même. Après avoir construit la majeure partie d'une application, j'ai une exigence de dernière minute pour prendre en charge la lecture/écriture dans une base de données supplémentaire (2 au total, pas d'autres connus). J'ai construit l'application en utilisant NHibernate, avec Autofac fournissant les composants DI/IoC. FWIW, cela réside dans une application ASP.NET MVC 2.Gestion de plusieurs bases de données avec NHibernate et Autofac
J'ai une classe de référentiel générique qui prend une session NHibernate. Théoriquement, je peux continuer à utiliser ce référentiel générique (IRepository<>
) pour la deuxième base de données tant que la session qui lui est passée est créée à partir d'une SessionFactory appropriée, n'est-ce pas?
Eh bien, lorsque l'application démarre, Autofac le fait. En ce qui concerne la session et SessionFactory, j'ai un module qui déclare:
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();
où ConfigureNHibernate(), qui retourne la SessionFactory de base, ressemble à:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
Actuellement, cela est limité à seulement la base de données unique. Dans n'importe quel autre scénario de NHib, je placerais probablement des instances de SessionFactories séparées dans un hachage, et les récupèrerais au besoin. Je ne veux pas avoir à réorganiser le tout car nous sommes assez proches d'une version majeure. Donc, je devine que j'ai besoin de modifier au moins les méthodes ci-dessus afin que je puisse configurer indépendamment deux SessionFactories. Ma zone grise est la façon dont je vais spécifier la bonne Usine à utiliser avec un référentiel spécifique (ou au moins pour les entités spécifiques à cette deuxième base de données).
Quelqu'un at-il l'expérience de ce scénario lors de l'utilisation d'un conteneur IoC et de NHibernate de cette manière?
EDIT J'ai écrasa une méthode GetSessionFactory qui prend un chemin de fichier de configuration, vérifie l'existence d'un SessionFactory correspondant dans la HttpRuntime.Cache, crée si l'on n'existe pas déjà une nouvelle instance, et renvoie cette SessionFactory. Maintenant, j'ai encore besoin de savoir comment dire à Autofac comment et quand spécifier un chemin de configuration approprié. La nouvelle méthode ressemble à (beaucoup emprunté après here de Billy 2006):
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;
}
Le stockage de la fabrique de sessions dans le cache est une mauvaise idée. Ce n'est pas quelque chose qui peut simplement disparaître et être recréé. –
Je sais. En réalité, je vais devoir gérer la durée de vie de cet objet mis en cache. L'exemple de Billy va même plus loin et crée une classe SessionManager portée par un singleton qui prend en charge les problèmes de mise en cache. J'essayais de le berner pour que Autofac puisse le gérer via ses propres mécanismes (très élégants). – nkirkes