所以我有多个数据库实例和一个Web应用程序。 根据网址名称,我知道我需要与之交谈的数据库实例。 我想改变旧的丑陋DAL以使用nhibernate,我想使用DI来做到这一点。 所以,让我说我有这个课程:
class CompanyDal(ISession session) //nhibernate session
{
Save(ICompany company)
{
session.Save(company)
}
}
所以我在创建DAL对象时注入了hibernate会话。但我的IOC需要知道要注入哪个会话,这意味着哪个连接字符串。 如果我只有一个单件工厂,我会得到错误的会话为不同的网址(不同的数据库)
我希望我解释一下,这样你们都可以理解。 谢谢
答案 0 :(得分:2)
假设所有数据库都具有相同的架构,您可以使用自定义DriverConnectionProvider动态切换连接。在下面的代码中,我将web.config中的连接字符串加载到字典中,然后使用URL中的“租户”路由值检索它们。
public class TenantConnectionProvider : DriverConnectionProvider
{
private IDictionary<string, string> _tenantConnectionStrings;
public override void Configure(IDictionary<string, string> settings)
{
// Load connection strings from config file
_tenantConnectionStrings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (ConnectionStringSettings connectionStringSetting in ConfigurationManager.ConnectionStrings)
{
_tenantConnectionStrings.Add(connectionStringSetting.Name, connectionStringSetting.ConnectionString);
}
base.Configure(settings);
}
public override IDbConnection GetConnection()
{
var connectionString = GetConnectionString(); //not shown, mine is for Web API
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
}
然后我使用Fluent NHibernate配置它:
// connection string has to be set even though custom provider is used
var config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("custom").Provider<TenantConnectionProvider>)
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<MyClass>();
});
答案 1 :(得分:0)
您必须拥有2个SessionFactories(每个数据库1个),并为每个会话注册一个命名会话。
我只使用Autofac(其他IoC应该也一样)
.Register<ISession>(factory1.OpenSession()).Named("f1");
.Register<ISession>(factory2.OpenSession()).Named("f2");
可以使用枚举而不是字符串。
鉴于会话以某种方式依赖于url(并且使用了IoC集成),我看到的唯一简单方法是使用激活处理程序:
.Register<IRepository>().OnActivating(e => {
var db = HttpContext.Current.Request.Url....//some code to find the db
var dep = e.Context.Resolve<ISession>("f1");
e.Instance.SetTheDependency(dep);})
或财产注入