我想我会在自己思考解决方案时提出这个问题。
在构建了大部分应用程序之后,我有最后一分钟要求支持读取/写入额外的数据库(总共 2 个,不知道其他数据库)。我使用 NHibernate 构建了应用程序,Autofac 提供了 DI/IoC 组件。FWIW,它驻留在 ASP.NET MVC 2 应用程序中。
我有一个接受 NHibernate 会话的通用存储库类。IRepository<>
从理论上讲,只要传递给它的会话是从适当的 SessionFactory 产生的,我就可以继续将这个通用存储库 ( ) 用于第二个数据库,对吗?
好吧,当应用程序启动时,Autofac 就是这样做的。关于 Session 和 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();
其中,返回基本 SessionFactory 的 ConfigureNHibernate() 如下所示:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
目前,这仅限于一个数据库。在任何其他 NHib 场景中,我可能会将单独的 SessionFactories 的实例推入散列,并根据需要检索它们。我不想重新设计整个东西,因为我们已经非常接近主要版本了。所以,我猜我至少需要修改上面的方法,以便我可以独立配置两个SessionFactories。我的灰色区域是我将如何指定正确的工厂用于特定的存储库(或至少用于特定于第二个数据库的实体)。
在以这种方式使用 IoC 容器和 NHibernate 时,任何人都有过这种情况的经验吗?
编辑 我已经删除了一个 GetSessionFactory 方法,该方法采用配置文件路径,检查 HttpRuntime.Cache 中是否存在匹配的 SessionFactory,如果不存在则创建一个新实例,并返回该 SessionFactory。现在我仍然需要敲定如何告诉 Autofac 如何以及何时指定适当的配置路径。新方法看起来像(大量从比利 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;
}