.net 使用NHibernate的Windows服务中的多个会话工厂

.net 使用NHibernate的Windows服务中的多个会话工厂,.net,nhibernate,session,service,.net,Nhibernate,Session,Service,我有一个连接到2个数据库的Webapp(一个核心,另一个是日志数据库) 我现在必须创建一个Windows服务,它将使用相同的业务逻辑/数据访问DLL。但是,当我尝试引用服务应用程序中的2个会话工厂并调用factory.GetCurrentSession()方法时,我收到错误消息“没有绑定到当前上下文的会话” 有人对如何做到这一点有什么建议吗 public class StaticSessionManager { public static readonly ISessionFactory

我有一个连接到2个数据库的Webapp(一个核心,另一个是日志数据库)

我现在必须创建一个Windows服务,它将使用相同的业务逻辑/数据访问DLL。但是,当我尝试引用服务应用程序中的2个会话工厂并调用factory.GetCurrentSession()方法时,我收到错误消息“没有绑定到当前上下文的会话”

有人对如何做到这一点有什么建议吗

public class StaticSessionManager
{
    public static readonly ISessionFactory SessionFactory;
    public static readonly ISessionFactory LoggingSessionFactory;

    static StaticSessionManager()
    {
         string fileName = System.Configuration.ConfigurationSettings.AppSettings["DefaultNHihbernateConfigFile"];
         string executingPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);
         fileName = executingPath + "\\" + fileName;
         SessionFactory = cfg.Configure(fileName).BuildSessionFactory();

         cfg = new Configuration();
         fileName = System.Configuration.ConfigurationSettings.AppSettings["LoggingNHihbernateConfigFile"];
         fileName = executingPath + "\\" + fileName;
         LoggingSessionFactory = cfg.Configure(fileName).BuildSessionFactory();
    }
}  
配置文件具有以下设置:

<property name="current_session_context_class">call</property>
最后,我尝试通过以下方式调用正确的工厂:

ISession session = StaticSessionManager.SessionFactory.GetCurrentSession();
有谁能提出更好的处理方法吗?
提前谢谢

Rob

我可以建议的第一件事是将您的
ISessionFactory
实例都设置为静态。这些应该是单例,因为实例化它们非常昂贵

编辑#1

您建议我在需要时创建会话,还是让它们保持打开状态

ISession
API在内部处理其连接。一段时间后,如果没有请求与基础数据库的交互,则连接将关闭,尽管您的
ISession
会保留其连接实例。一旦需要对数据库执行一些其他事务,它就会重新打开以前使用的连接

要回答您的问题,首选的方法是每页(Web)或每表单(桌面)使用
ISession
API实例。例如,让我们考虑你有一个会计软件,并且用户对客户有一些管理要做。然后,当加载
CustomerMgmtForm
时,您应该提供
ISession
的实例,以便它可以加载您的客户,跟踪您的更改、删除和创建的新客户(一旦加入
ISession
,以便在调用
SaveOrUpdate()时
方法,ISession知道它与跟踪的更改和瞬态实体有什么关系

你想知道为什么每页或每张表格都有一个实例

由于
ISession
API跟踪对象发生的每一次更改,想象一下,一旦加载了客户、供应商和其他实体,您就必须在应用程序中小心处理。对客户执行的每一次更改,他们都无权对供应商进行更改。但这些客户仍然会在那里,因为是您为客户使用的
ISession
实例!然后,您的应用程序对内存的要求随着加载的对象数量的增加而增加。此外,众所周知,当
ISession
在内存中增长过大时,可能会导致一些内存泄漏,然后被NHibernate视为无效会话,放弃所有未保存的更改和所有内容,因为跟踪实体的会话现在无效

除此之外,当您打开CustomerMgmtForm(比如CustomerMgmtForm)时,您将不得不管理客户实体。一旦您关闭了表单,甚至打开了SuppliersMgmtForm(您将在其中管理供应商),您就很可能不必跟踪您的客户。这样,您将有两个他
ISession
API:第一个-
customerMgmtSession
,另一个-
供应商MgmtSession
。因此,它们不应该变得太大而导致内存泄漏,因为它们都有自己的实体需要处理或维护。两者都完全独立

按照这种方法,您应该关闭并处理Windows窗体的
ISession
API on FormClosing事件实例,或Web中的任何等效实例。因此,现在,在Windows服务中,您可以决定什么是最理想的情况,并根据您的se决定在哪里最适合您的需要是的

但是有一件事,如果您的服务不需要对您的实体保留任何更改或任何跟踪,那么
IStatelessSession
API可能更适合使用。使用它,我肯定建议您仅在需要与底层数据库交互时才打开或实例化无状态会话,因为
IStatelessSession
保持活动状态是没有用的,因为它没有提供资源来跟踪对实体执行的更改。如果我没记错的话,这只是
ISession
IStatelessSession
API之间的主要区别

编辑#2

如上所述,这样做也可以帮助您解决问题,因为您永远不需要调用
ISessionFactory.GetCurrentSession()


我希望这能有所帮助!=)

这是一个很好的观点——我现在已经改变了这一点,尽管我的工作假设是我只创建了一次工厂。您建议我在需要时创建会话,还是让会话保持打开状态?请参阅我的编辑#1以获取您在评论中提出的问题的答案。=)这是一个很好的解释,谢谢你花时间!我现在要和几个同事讨论这个问题,看看我们是否需要对代码进行一些修改,以便在两个平台上都能正常工作。再次感谢!你的问题解决了我的问题:)谢谢。
ISession session = StaticSessionManager.SessionFactory.GetCurrentSession();