【问题标题】:using nHibernate with multi DB instances with DI将 nHibernate 与带有 DI 的多数据库实例一起使用
【发布时间】:2014-03-20 04:48:48
【问题描述】:

所以我有多个数据库实例和一个 Web 应用程序。 根据 url 名称,我知道我需要与之交谈的数据库实例。 我想将旧的丑陋 DAL 更改为与 nhibernate 一起使用,并且我想使用 DI 来做到这一点。 所以,假设我有这个课程:

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

所以我在创建 DAL 对象时注入了休眠会话。但我的 IOC 需要知道要注入哪个会话,即哪个连接字符串。 如果我只有一个单例工厂,我会为不同的 url(不同的 db)得到错误的会话

我希望我解释了它,以便大家都能理解。 谢谢

【问题讨论】:

    标签: hibernate nhibernate data-access-layer


    【解决方案1】:

    假设所有数据库具有相同的架构,您可以使用自定义 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>();
        });
    

    【讨论】:

    • 感谢您的回复。但我想将 ISession 注入 DAO 对象。现在 IOC 怎么知道在运行时注入哪个 ISession?
    • 假设您使用的是每个请求的会话,那么只有一个 ISession。每次创建会话时,会话工厂将使用自定义 DriverConnectionProvider 提供的连接来提供会话。依赖注入框架只需要注入ISession,没有别的。
    【解决方案2】:

    您必须拥有 2 个 SessionFactories(每个 db 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);})
    

    或属性注入

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 2017-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多