Nhibernate SessionFactory-一个工厂用于多个数据库

Nhibernate SessionFactory-一个工厂用于多个数据库,nhibernate,sessionfactory,Nhibernate,Sessionfactory,在这种情况下,我们有多个具有相同模式的数据库,但每个数据库中的数据不同。我们正在创建一个会话工厂来处理这个问题 问题是,我们不知道我们将连接到哪个数据库,直到运行时,我们才能提供。但是在启动时,为了获得工厂构建,我们需要连接到具有该模式的数据库。目前,我们通过在已知位置创建模式并使用它来实现这一点,但我们希望删除该要求 我无法找到在不指定连接的情况下创建会话工厂的方法。我们不希望能够使用没有参数的OpenSession方法,这没关系 有什么想法吗? 谢谢 Andy实现您自己的IConnectio

在这种情况下,我们有多个具有相同模式的数据库,但每个数据库中的数据不同。我们正在创建一个会话工厂来处理这个问题

问题是,我们不知道我们将连接到哪个数据库,直到运行时,我们才能提供。但是在启动时,为了获得工厂构建,我们需要连接到具有该模式的数据库。目前,我们通过在已知位置创建模式并使用它来实现这一点,但我们希望删除该要求

我无法找到在不指定连接的情况下创建会话工厂的方法。我们不希望能够使用没有参数的OpenSession方法,这没关系

有什么想法吗? 谢谢
Andy

实现您自己的
IConnectionProvider
或者将您自己的连接传递到
ISessionFactory.OpenSession(IDbConnection)
(但是请阅读该方法关于连接跟踪的注释)

我们提出的解决方案是创建一个类来为我们管理它。该类可以使用方法调用中的一些信息来执行一些路由逻辑,以确定数据库的位置,然后通过连接字符串调用OpenSession。

您也可以使用brady gaster提供的great NuGet包来实现这一点。我从他的NHQS软件包中实现了我自己的程序,它运行得非常好

你可以在这里找到它:


祝你好运

遇到这个问题,我想为未来的读者添加我的解决方案,这基本上是Mauricio Scheffer所建议的,它封装了CS的“切换”,并提供了单点管理(我喜欢这样做,而不是必须传递到每个会话调用中,少了“错过”和出错)

我在客户端身份验证期间获取ConnectionString并在上下文上设置,然后使用以下IConnectinProvider实现,在每次打开会话时为CS设置该值:

/// <summary>
/// Provides ability to switch connection strings of an NHibernate Session Factory (use same factory for multiple, dynamically specified, database connections)
/// </summary>
public class DynamicDriverConnectionProvider : DriverConnectionProvider, IConnectionProvider
{
    protected override string ConnectionString
    {
        get
        {
            var cxnObj = IsWebContext ?
                HttpContext.Current.Items["RequestConnectionString"]: 
                System.Runtime.Remoting.Messaging.CallContext.GetData("RequestConnectionString");

            if (cxnObj != null)
                return cxnObj.ToString();
            //catch on app startup when there is not request connection string yet set
            return base.ConnectionString;
        }
    }

    private static bool IsWebContext
    {
        get { return (HttpContext.Current != null); }
    }
}
//
///提供切换NHibernate会话工厂的连接字符串的能力(对多个动态指定的数据库连接使用同一工厂)
/// 
公共类DynamicDriveConnectionProvider:DriverConnectionProvider、IConnectionProvider
{
受保护的重写字符串连接字符串
{
得到
{
var cxnObj=IsWebContext?
HttpContext.Current.Items[“RequestConnectionString”]:
System.Runtime.Remoting.Messaging.CallContext.GetData(“RequestConnectionString”);
if(cxnObj!=null)
返回cxnObj.ToString();
//尚未设置请求连接字符串时在应用程序启动时捕获
返回base.ConnectionString;
}
}
私有静态bool-IsWebContext
{
获取{return(HttpContext.Current!=null);}
}
}
然后在NHConfig期间将其连接:

var configuration = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2005
                            .Provider<DynamicDriverConnectionProvider>() //Like so
var-configuration=fluntly.Configure()
.数据库(MsSqlConfiguration.MsSql2005
.Provider()//像这样

为什么不在运行时在
配置
对象中提供连接详细信息,而不是在编译时在配置文件中提供连接详细信息?为什么要这样做?我很好奇…@Kent:是的,问题是我们构建工厂的时间点(启动时)我们实际上不需要连接,但建立连接时,用户不必等待连接真正打开。@Pierre:可扩展性和正常运行时间。相同的数据最终会出现在多个地方,但流量较高的客户可能会拥有自己的服务器,而流量较低的客户可以共享,而一个系统故障则不会把每个人都记下来。如果你有一个带复制的数据库集群,你不必有两个连接字符串。检查这个答案:愿意为我们提供一个例子吗?Mauricio,谢谢,我会检查一下。我曾考虑过你的后一个建议,但我的研究不清楚NHibernate是否会关闭连接,或者我们是否会关于责任。我会详细了解IConnectionProvider,它看起来可能更接近我们所需要的。