我正在开发和作为Windows服务运行的应用程序。还有其他组件包括一些WCF服务,客户端GUI等等 - 但它是访问数据库的Windows服务。
因此,该应用程序是一个长期运行的服务器,我想提高其性能和可伸缩性,我希望改进数据访问等。我发布了另一个关于二级缓存的帖子。
这篇文章是关于访问数据库的长期运行线程的会话管理。 我应该使用线程静态上下文吗? 如果是这样,是否有任何关于如何实施的例子。
网络上每个使用NHibernate的人似乎都非常关注网络应用程序风格的架构。对于非Web应用程序设计,似乎缺乏文档/讨论。
目前,我的长期运行线程就是这样做的:
因此,以下是我们为每种DAO方法使用的常见模式:
对于对DAO类的每个方法调用都会发生这种情况。 我怀疑这是我们这样做的一种反模式。
但是,我无法在任何地方找到足够的方向来改进它。
请注意,虽然这个线程在后台运行,做其中的东西,有来自WCF客户端的请求,每个客户端都可以自己进行2-3个DAO调用 - 有时候查询/更新长时间运行的相同对象线程处理。
我们将非常感谢任何改进我们设计的想法/建议/指示。 如果我们能够进行一些很好的讨论,我们可以将其作为社区维基,并可以从http://nhibernate.info
链接到此处克里希纳
答案 0 :(得分:7)
对于非网络应用程序设计,似乎缺乏文档/讨论。
这也是我的经历。但是,您所关注的模型对我来说似乎是正确的。您应该始终打开会话,提交更改,然后再次关闭它。
答案 1 :(得分:1)
这个问题现在有点老了,但另一种技术是使用Contextual Sessions而不是在每个DAO中创建一个新会话。
在我们的例子中,我们考虑为每个线程创建一次会话(对于我们的多线程win32服务),并使用返回SessionFactory.GetCurrentSession()的属性将其提供给DAO(使用ThreadContext当前会话提供程序,因此它是每个线程的会话)或通过DI(依赖注入 - 再次使用ThreadContext。)
More info on GetCurrentSession and Contextual Sessions here。
答案 2 :(得分:0)
我同意,有状态应用程序的示例并不多。 我正在考虑做以下事情:
和我一样,我有一个托管多个WCF服务的Windows服务。所以WCF服务是切入点。 最终,我的所有WCF服务都继承自AbstractService - 它处理大量日志记录和基本数据库插入/更新。
在我见过的最好的NHibernate帖子中,HttpModule执行以下操作: 见http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
private void BeginTransaction(object sender, EventArgs e) {
NHibernateSessionManager.Instance.BeginTransaction();
}
private void CommitAndCloseSession(object sender, EventArgs e) {
try {
NHibernateSessionManager.Instance.CommitTransaction();
}
finally {
NHibernateSessionManager.Instance.CloseSession();
}
}
所以也许我应该在AbstractService中做类似的事情。因此,我将最终得到每个服务调用的会话。如果您查看上面的NHib最佳实践文章链接,您将看到NHibernateSessionManager应该处理其他所有内容,只要我打开并关闭会话(AbstractService构造函数和析构函数)。
只是一个想法。但是我遇到了错误,因为我的会话似乎停留了太长时间,而且我得到了臭名昭着的错误 - NHibernate.AssertionFailure:条目中的空id(在发生异常后不要刷新会话)。
答案 3 :(得分:0)
您也可以在不实际关闭会话的情况下刷新会话,并实现同样的目的。我做。
答案 4 :(得分:0)
我们最近开始使用IoC容器来管理会话生命周期,以替代上面提到的上下文会话。 (更多细节here)。