12

我正在开发和作为 Windows 服务运行的应用程序。还有其他组件,包括一些 WCF 服务、客户端 GUI 等 - 但访问数据库的是 Windows 服务。

因此,该应用程序是一个长时间运行的服务器,我想提高它的性能和可扩展性,我希望改进数据访问等。我在另一个线程中发布了关于二级缓存的帖子。

这篇文章是关于访问数据库的长时间运行线程的会话管理。我应该使用线程静态上下文吗?如果是这样,是否有任何示例说明如何实施。

网络上所有使用 NHibernate 的人似乎都非常关注 Web 应用程序风格的架构。似乎非常缺乏非 Web 应用程序设计的文档/讨论。

目前,我长期运行的线程这样做:

  1. 调用 3 或 4 个 DAO 方法
  2. 验证返回的分离对象的状态。
  3. 如果需要,更新状态。
  4. 调用几个 DAO 方法来持久化更新的实例。(传入对象的 id 和实例本身 - DAO 将再次从数据库中检索对象,并在提交事务之前设置更新的值和 session.SaveOrUpdate()。
  5. 睡眠'n'秒
  6. 再重复一遍!

因此,以下是我们用于每个 DAO 方法的常见模式:

  • 使用 sessionFactory.OpenSession() 打开会话
  • 开始交易
  • 做数据库工作。检索/更新等
  • 提交反式
  • (异常情况下回滚)
  • 最后总是处理事务和 session.Close()

对 DAO 类的每个方法调用都会发生这种情况。我怀疑这是我们正在做的某种反模式。

但是,我无法在任何地方找到足够的方向来改进它。

请注意,当这个线程在后台运行时,做它的工作,有来自 WCF 客户端的请求,每个客户端都可以自己调用 2-3 个 DAO - 有时查询/更新长时间运行的线程处理的相同对象.

任何改进我们设计的想法/建议/指针将不胜感激。如果我们能进行一些很好的讨论,我们可以把它变成一个社区维基,并可能从http://nhibernate.info链接到这里

克里希纳

4

5 回答 5

7

似乎非常缺乏非 Web 应用程序设计的文档/讨论。

这也是我的经历。但是,您所遵循的模型对我来说似乎是正确的。您应该始终打开一个会话,提交更改,然后再次关闭它。

于 2008-10-05T08:45:23.773 回答
1

这个问题现在有点老了,但另一种技术是使用上下文会话而不是在每个 DAO 中创建一个新会话。

在我们的例子中,我们正在考虑为每个线程创建一次会话(对于我们的多线程 win32 服务),并使用返回 SessionFactory.GetCurrentSession() 的属性(使用 ThreadContext 当前会话提供程序)使其对 DAO 可用,所以它是每线程会话)或通过 DI(依赖注入 - 再次使用 ThreadContext。)

有关 GetCurrentSession 和上下文会话的更多信息

于 2011-03-03T14:25:03.057 回答
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 中做类似的事情。如此有效地,我最终会为每个服务调用提供一个会话。如果您检查上面的 NHibernate 最佳实践文章链接,您会发现 NHibernateSessionManager 应该处理其他所有事情,只要我打开和关闭会话(AbstractService 构造函数和析构函数)。

只是一个想法。但是我遇到了错误,因为我的会话似乎停留了太久,并且我遇到了臭名昭著的错误 - NHibernate.AssertionFailure: null id in entry(发生异常后不要刷新会话)。

于 2008-11-27T16:32:42.093 回答
0

您也可以在不实际关闭会话的情况下刷新会话,它可以实现相同的效果。我愿意。

于 2010-03-11T21:51:44.997 回答
0

我们最近开始使用 IoC 容器来管理会话生命周期,作为上述上下文会话的替代品。(更多细节在这里)。

于 2011-05-04T15:03:07.147 回答