NHibernate:创建一个ConnectionProvider,动态选择要连接的几个数据库中的哪一个?

Dav*_*gue 7 nhibernate

我有一个连接到许多SQL Server数据库的项目.它们都具有相同的模式,但数据不同.数据基本上由客户分开.当请求进入asp.net应用程序时,它可以告诉需要哪个数据库并设置会话.

我们现在正在做的是为每个客户数据库创建一个新的SessionFactory.这已经好了一段时间,但随着更多的客户,我们正在创建更多的数据库.我们开始遇到内存问题,因为每个工厂都有自己的QueryPlanCache.我写了一篇关于调试内存的帖子.

我想这样做,以便我们有一个SessionFactory使用ConnectionProvider打开与正确数据库的连接.到目前为止我看到的是这样的:

public class DatabaseSpecificConnectionProvider : DriverConnectionProvider
{
    public override IDbConnection GetConnection()
    {
        if (!ThreadConnectionString.HasValue)
            return base.GetConnection();

        var connection = Driver.CreateConnection();
        try
        {
            connection.ConnectionString = ThreadConnectionString.Value;
            connection.Open();
        }
        catch(DbException)
        {
            connection.Dispose();
            throw;
        }
        return connection;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果只需要一个数据库来处理请求,那么这很有用,因为我可以在启动期间在线程局部变量中设置连接字符串.我遇到麻烦的地方是我有一个需要访问多个数据库的管理员级操作.

由于ConnectionProvider不知道哪个会话正在打开连接,因此无法决定使用哪个会话.我可以在打开会话之前设置一个线程局部变量,但由于会话连接是懒惰打开的,所以有麻烦.

我还需要创建一个CacheProvider来避免缓存分裂.那将会遇到类似的问题.

那么任何想法?或者这只是从NHibernate那里得到的太多了?

编辑:我发现这个答案表明我必须依赖一些我想避免的全球状态.如果我有多个活动会话,我希望ConnectionProvider响应与相应数据库的连接.

编辑2:我倾向于为每个站点始终使用的默认Session创建ConnectionProvider的解决方案.然后,为了连接到其他数据库,我打开连接并传入它.我可以看到的缺点是我不能在辅助会话上使用二级缓存,我将不得不跟踪和关闭连接我.

Dav*_*gue 2

我已经确定了一个解决方法,并将其列在这里,以防有人再次遇到此问题。

事实证明我无论如何也找不到让 ConnectionProvider 根据会话更改数据库的方法。它实际上只能取决于当前请求的上下文。

就我而言,95% 的情况下只需要一个客户的数据库。我创建了一个 SessionFactory 和一个 ConnectionProvider 来处理这个问题。对于其余的极端情况,我创建了第二个 SessionFactory,当我打开会话时,我传递一个新的连接。

这样做的缺点是与第二个数据库通信的会话无法使用二级缓存,并且我必须确保在请求结束时关闭连接。

目前看来效果很好,但我很好奇从长远来看它的效果如何。