【问题标题】:NHibernate session management in Windows Service applicationsWindows 服务应用程序中的 NHibernate 会话管理
【发布时间】:2010-09-15 08:41:13
【问题描述】:

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

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

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

网络上所有使用 NHibernate 的人似乎都非常关注 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 - 有时会在长时间运行时查询/更新相同的对象线程处理。

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

奎师那

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    我同意,有状态应用的示例并不多。 我正在考虑执行以下操作:

    和你一样,我有一个托管许多 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(发生异常后不要刷新会话)。

    【讨论】:

      【解决方案2】:

      我们最近开始使用 IoC 容器来管理会话生命周期,以替代上述上下文会话。 (更多详情here)。

      【讨论】:

        【解决方案3】:

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

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

        More info on GetCurrentSession and Contextual Sessions here

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

            似乎非常缺乏关于非网络应用程序设计的文档/讨论。

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

            【讨论】:

            • +1。我多次看到这个一般建议:SessionFactory 很昂贵。只创建一次。会议很便宜。
            猜你喜欢
            • 1970-01-01
            • 2012-07-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多