StructureMap、NHibernate 和多个数据库
我正在使用 Fluent NHibernate 开发 Asp.Net MVC 3 应用程序。我只是尝试使用 StructureMap 添加 IoC 容器。
我已经实现了一个自定义控制器工厂,它使用 StructureMap 来创建控制器并注入依赖项。每个控制器构造函数都采用一个或多个服务,而这些服务又采用 DAO 作为构造函数参数。每个 DAO 构造函数都采用一个 ISessionFactory。
对于我的 StructureMap NHibernate 注册表,我有以下内容:
internal class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
For<ISessionFactory>()
.Singleton()
.Use(x => new AppSessionFactory().GetSessionFactory(connectionString));
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(x => x.GetInstance<ISessionFactory>().OpenSession());
}
}
public class AppSessionFactory
{
public ISessionFactory GetSessionFactory(string connectionString)
{
return GetConfig(connectionString)
.BuildSessionFactory();
}
public static FluentConfiguration GetConfig(string connectionString)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
.Mappings(
x => x.FluentMappings.AddFromAssemblyOf<AppEntity>());
}
}
这对于单个数据库和单个会话工厂来说都工作得很好。然而,该应用程序使用多个数据库。
处理这个问题的最佳方法是什么?
I'm working on an Asp.Net MVC 3 application using Fluent NHibernate. I'm just attempting to add an IoC container using StructureMap.
I have implemented a custom controller factory which uses StructureMap to create the controller and inject dependencies. Each controller constructor takes one or more services, which in turn take a DAO as constructor argument. Each DAO constructor takes an ISessionFactory.
For my StructureMap NHibernate registry I have the following:
internal class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;
For<ISessionFactory>()
.Singleton()
.Use(x => new AppSessionFactory().GetSessionFactory(connectionString));
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(x => x.GetInstance<ISessionFactory>().OpenSession());
}
}
public class AppSessionFactory
{
public ISessionFactory GetSessionFactory(string connectionString)
{
return GetConfig(connectionString)
.BuildSessionFactory();
}
public static FluentConfiguration GetConfig(string connectionString)
{
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
.Mappings(
x => x.FluentMappings.AddFromAssemblyOf<AppEntity>());
}
}
This all works fine for a single database and single session factory. However the application uses multiple databases.
What is the best way to handle this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
注册多个会话工厂很容易 - 问题是在需要时选择正确的会话工厂。例如,假设我们有一个拥有多个数据库的实验室。每个实验室都有一个位置和该位置的多个样本。我们可以有一个 SampleRepository 来模拟它。每个位置都有一个唯一的键来识别它(例如“LabX”、“LabY”、“BlackMesa”)。我们可以使用该唯一键作为 app.config 文件中数据库连接字符串的名称。在此示例中,我们将在 app.config 文件中包含三个连接字符串。这是一个示例连接字符串部分:
因此,我们需要为每个连接字符串拥有一个唯一的会话工厂。让我们创建一个包装 ISessionFactory 的 NamedSessionFactory:
现在我们需要稍微修改一下您的 AppSessionFactory。首先,您创建的是一个会话工厂 - 这并不是我们正在寻找的。我们想要给我们的工厂一个位置并从中获取一个会话,而不是一个会话工厂。 Fluent NHibernate 为我们提供了会话工厂。
这里的技巧是在构造函数中接受 INamedSessionFactory 对象的列表。 StructureMap 应该为我们提供我们已注册的所有 INamedSessionFactory 对象。我们稍后会进行注册。
这就是奇迹发生的地方。给定一个位置键,我们遍历工厂列表,寻找与 locationKey 名称相同的工厂,然后要求它打开一个会话并将其返回给调用者。
现在让我们把这一切连接在一起。
我们将循环遍历 app.config 文件中的所有连接字符串(本示例中将包含三个连接字符串),并为每个连接字符串注册一个 INamedSessionFactory 对象。
我们还需要注册IAppSessionFactory。
您会注意到,我们已将此逻辑移出工厂类...这些是从 Fluent NHibernate 创建会话工厂的辅助方法。
应该这样做!让我们创建一个用于获取示例的存储库...
现在您可以获取 SampleRepository 的单个实例,并使用 GetSamplesForLocation 方法从我们在 app.config 中注册的三个数据库中的任何一个中提取示例。不过可能想避开 BlackMesa。我知道那里存在问题。
Registering multiple session factories is easy - the problem is selecting the right one when you need it. For example, let's say we have some sort of laboratory that has multiple databases. Each lab has a Location and multiple Samples for that location. We could have a SampleRepository that models that. Each Location has a unique key to identify it (e.g. "LabX", "LabY", "BlackMesa"). We can use that unique key as the name of the database connection string in the app.config file. In this example, we would have three connection strings in the app.config file. Here's a sample connectionStrings section:
Thus, we need to have a unique session factory for each connection string. Let's create a NamedSessionFactory that wraps ISessionFactory:
Now we need to modify your AppSessionFactory a bit. First off, what you've created is a session factory factory - that's not quite what we're looking for. We want to give our factory a location and get a session out of it, not a session factory. Fluent NHibernate is what gives us session factories.
The trick here is accept a list of INamedSessionFactory objects in the constructor. StructureMap should give us all of the INamedSessionFactory objects that we've registered. We'll get to registration in a second.
This is where the magic happens. Given a location key, we run through our list of factories looking for one with the same name as locationKey, then ask it to open a session and return it to the caller.
Now let's wire this all together.
We're going to loop through all of the connection strings in our app.config file (there would be three of them in this example) and register an INamedSessionFactory object for each one.
We also need to register IAppSessionFactory.
You'll notice that we've moved this logic out of the factory class... These are helper methods for creating session factories from Fluent NHibernate.
That should do it! Let's create a repository for getting at our samples...
Now you can get a single instance of SampleRepository and use the GetSamplesForLocation method to pull samples from any of the three databases we have registered in app.config. Might want to avoid BlackMesa though. I understand there were problems there.
你确定这东西有效吗? 字符串 ISessionFactory
应该是
Are you sure this thing works? string ISessionFactory
should this be