【问题标题】:nhibernate RollbackTransaction and why to dispose of session after rollback?nhibernate RollbackTransaction 以及为什么在回滚后处理会话?
【发布时间】:2014-11-12 04:23:45
【问题描述】:

我正在使用 nhibernate 开发一个系统,我在异常捕获块中看到很多以下两行:

session.Flush();
session.RollbackTransaction();

我被这个逻辑搞糊涂了,看起来是不必要的工作来刷新更改,然后使用事务回滚做法。

我想设置一个参数来删除这些刷新调用并仅依赖 RollbackTransaction 方法,但我遇到了这个question。接下来,我阅读了更多链接的文档,并阅读了以下信息:

如果你回滚事务,你应该立即关闭并丢弃当前会话,以确保 NHibernate 的内部状态是一致的。

这是什么意思?我们目前将 Session 生命周期与 Web 请求的开始和结束操作配对,所以我担心我们调用 flush THEN 回滚的原因是为了保持会话处于有效状态。

有什么想法吗?

【问题讨论】:

  • 有一点很清楚:在回滚之前调用 flush 是多余的。它在代码中的任何地方使用的事实并没有改变这一事实。而且,如文档中所述 - 回滚后应立即结束会话。这就是为什么我们应该在网络中对写入和读取有特殊要求。如果写操作/请求/工作单元的某些部分失败 - 回滚,返回错误消息,消失会话..

标签: nhibernate transactions rollback


【解决方案1】:

Rollback 之前的这个Flush 很可能是一个解决应用程序错误的技巧,该错误是在回滚后重用会话引起的。

正如您自己发现的那样,回滚后不得使用会话。根据您的comment,该应用程序正在犯该错误。

如果在Rollback 之前没有Flush,会话仍将更改视为待处理,并将在下一个Flush 提交它们,从而破坏了Rollback 的目的。在回滚之前执行 Flush 会导致刷新挂起的更改,然后回滚,有助于避免会话稍后刷新它们。

但是会话仍然没有处于一致的状态,所以继续使用它,应用程序仍然处于危险之中。会话缓存仍然保存尝试然后回滚的更改。会话不再将它们视为等待刷新的未决更改。如果应用程序稍后使用会话访问这些实体,它们的状态仍将是回滚事务中修改后的状态,尽管它们不会被认为是脏的。

【讨论】:

    【解决方案2】:

    NHibernate 通过会话进行对象跟踪,并且您对实体所做的所有更改都存储在那里,当您执行刷新时,这些更改将写入数据库。如果您在这样做时遇到异常,则会话状态与数据库状态不一致,因此如果您在此阶段进行回滚,它将回滚数据库事务,但不会回滚会话值。

    根据设计,一旦发生这种情况,不应以可靠的方式进一步使用会话(即使 Session.Clear() 也无济于事)

    如果您使用每个请求的会话并且如果您收到错误,最好的方法是向用户显示错误并要求重试该操作。其他选择是创建一个全新的会话并将其用于获取数据以显示错误。

    【讨论】:

    • 那么你会建议如果我有额外的项目需要记录在数据库中而不管失败,我们应该在相同的回滚逻辑中创建一个新会话吗?
    • 是的,这是你应该做的。
    • 太棒了。感谢您帮助澄清使用 nhibernate 的细微差别!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多