事务如何在 nhibernate 中工作?

Posted

技术标签:

【中文标题】事务如何在 nhibernate 中工作?【英文标题】:How do transactions work in nhibernate? 【发布时间】:2011-06-05 16:39:43 【问题描述】:

我刚开始学习 nHibernate,我对事务感到困惑。我知道 nhibernate 会跟踪会话中对持久对象的所有更改,并且这些更改会在提交时发送到数据库,但是事务的目的是什么?

如果我将代码包装在“使用事务”块中并调用 commit,它是仅提交事务中发生的对象更改,还是提交自上次提交刷新以来会话中发生的所有更改?

【问题讨论】:

【参考方案1】:

事务的目的是确保您不会提交带有脏数据或错误的会话。考虑一个非常简单的订购书的交易案例。

您可能会执行以下操作: a) 检查该书此时是否存在。 b) 阅读客户的详细信息,看看他的购物车中是否有任何东西。 c) 更新图书数量 d) 输入订单

现在考虑在输入订单时遇到错误的情况,因为您希望回滚其他更改,即在您回滚事务时。

你是怎么做到的?那么有很多方法。 Web 应用程序的一种方法是监视 HTTP 错误对象,如下所示:

if(HttpContext.Current != null && HttpContext.Current.Error != null)
transaction.Rollback();

理想情况下,您不应该通过使用显式事务块来破坏您的工作单元模式。尽量避免这样做

【讨论】:

我很困惑,这篇文章说我应该对所有事情都使用显式事务,但你说使用这些会破坏“工作单元”模式。 nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions 我相信他的意思是事务不应该直接在服务/存储库方法中使用。更好的方法是创建一个 ActionFilter 或一个 HTTP 模块来启动事务并根据是否存在异常来提交/回滚。 Matthew 的第一条评论指出,即使您没有明确设置事务,nhibernate 仍然会将整个事物作为事务发送。这与在 HttpModule 中显式设置一个有何不同?【参考方案2】:

如果您不使用事务,那么任何时候 NHibernate 发送一个批次,这本身就是一个事务。我不确定 session.Flush() 是否使用批处理。让我们假设它确实如此。您对 session.Flush() 的第一次调用将导致事务。假设您对刷新的第二次调用导致错误。第一次刷新的更改将保留在数据库中。

另一方面,如果您使用的是显式事务,则可以调用一百万次刷新,但如果您回滚事务(可能是因为第 10 万次刷新引发了错误),那么所有刷新都会回滚。

希望这是有道理的。

【讨论】:

我仍然难以掌握的是对象跟踪。显式事务如何影响全局对象跟踪?假设一个持久对象在显式事务之外更改(现在很脏),但我还没有提交。接下来是一个显式事务,它运行一些查询然后提交。对显式事务之外的对象的更改也会被提交吗?这让我很困惑。

以上是关于事务如何在 nhibernate 中工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何使事务在 Grails 中工作

锁定如何在 insert...select 语句中工作?

ACID 如何在宁静的微服务架构中工作

NHibernate教程(19) —— 一级缓存

如何结合 NHibernate Fluent 和 WPF-NHibernate 工具包中的 VmWrapper-Classes?

NHibernate 2 + Fluent Nhibernate 中等信任