使用带有DI的多数据库实例的nHibernate

时间:2014-02-19 17:13:09

标签: hibernate nhibernate data-access-layer

所以我有多个数据库实例和一个Web应用程序。 根据网址名称,我知道我需要与之交谈的数据库实例。 我想改变旧的丑陋DAL以使用nhibernate,我想使用DI来做到这一点。 所以,让我说我有这个课程:

class CompanyDal(ISession session) //nhibernate session
{
    Save(ICompany company)
    { 
        session.Save(company)
    }
}

所以我在创建DAL对象时注入了hibernate会话。但我的IOC需要知道要注入哪个会话,这意味着哪个连接字符串。 如果我只有一个单件工厂,我会得到错误的会话为不同的网址(不同的数据库)

我希望我解释一下,这样你们都可以理解。 谢谢

2 个答案:

答案 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);})

或财产注入