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

时间:2012-02-01 18:46:41

标签: nhibernate

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

我们现在正在做的是为每个客户数据库创建一个新的SessionFactory。这已经好了一段时间,但随着更多的客户,我们正在创建更多的数据库。我们开始遇到内存问题,因为每个工厂都有自己的QueryPlanCache。 I wrote a post about my debugging of the memory

我想这样做,以便我们有一个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;
    }
}

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

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

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

那么任何想法?或者这只是从NHibernate那里要求太多了?

编辑:我发现this answer that suggests I'd have to rely on some global state这是我想避免的。如果我有多个活动会话,我希望ConnectionProvider通过与相应数据库的连接进行响应。

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

1 个答案:

答案 0 :(得分:1)

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

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

就我而言,95%的时间只需要一个客户的数据库。我创建了一个SessionFactory和一个可以处理它的ConnectionProvider。对于剩下的极端情况,我创建了第二个SessionFactory,当我打开Session时,我传入一个新的Connection。

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

现在似乎运作良好,但我很好奇它从长远来看会有多好。