繁体   English   中英

NHibernate读取事务

[英]NHibernate Transactions on Reads

我已经阅读了文档和解释为什么强烈建议在NH中使用读取操作的事务。 但是,我还没有完全“买进”它。 有人可以试着解释它而不只是告诉我RTFM,我已经做过了吗? ;)

其中一位作者的这篇文章可能有你的答案:

即使我们只读取数据,我们也希望使用事务,因为使用事务确保我们从数据库中获得一致的结果。 NHibernate假设对数据库的所有访问都是在事务下完成的,并强烈反对在没有事务的情况下使用会话。

撇开处理交易的安全问题,假设交易成本高昂且我们需要对其进行优化是假的。 如前所述,数据库始终在事务中运行。 数据库已经过大量优化,可以处理事务。 问题是这是每个声明还是每批。 创建和处理事务需要完成一些工作,并且每个语句必须执行它实际上比每批执行它更昂贵。

其他人所说的是真的,但是他们没有指出不自行控制事务的问题是如果你在没有显式事务的情况下执行几个NHibernate操作,那么每个操作都将在单独的事务中进行

因此,您可以轻松地获得操作之间的不一致。 通过显式启动NHibernate事务然后执行其中的操作,可以保证这些操作的一致性。

当然,对于任何隐式启动事务的数据访问层,如果不这样做,这是正确的。 它不仅限于NHibernate。

var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);

如果某个其他事务在两个查询之间从Bar中删除行,该怎么办? 您将遇到幻像数据问题。 这不是NHibernate的具体问题。 在不使用事务的情况下,您将遇到与任何其他类型的数据库访问相同的问题。 您应该阅读有关交易的手册,而不是NHiberante手册。

让我们关注如果你使用交易会发生什么。 在处理结束时,但在开始读取数据(即View)之前关闭Session是习惯的,但不是强制性的。 此方法在术语“ 在视图中打开会话 ”下传播(尽管它显然具有防止在关闭之前读取的模式)。 此模式通常用于Web应用程序,其中会话在请求到达时打开,并在写入响应流之前关闭。

(N)Hibernate需要会话和事务。 当您在不使用显式交易的情况下阅读时,将为您设置交易。 在提交事务后读取时,行为取决于NH配置和驱动程序。

ODBC和JDBC都没有定义连接关闭时发生的情况以及未提交或未返回的数据。 重新打开连接后,可能会自动启动新事务。

使用非事务性访问只能与NHibernate配置中显式设置auto-commit一起使用。 如果没有,则使用驱动程序的默认值,它可能有效,或者可能无效。

简而言之,当您不在读取上使用事务时,存在许多缺点和未定义的行为。 它会经常工作,但这取决于配置,应用的模式,驱动程序。 您很有可能获得LazyInitializationException ,这是在提交后读取而不打开新事务的常见结果。

“最佳实践”是将一个事务用于读/写,另一个用于只读。 这在前面的链接“我可以在会话中使用两个事务”部分进行了简要描述,但需要更多的实现。

它不仅是“使用事务进行读取”,它还是:“使用您用于写入的相同事务进行读取”。 (然后,虽然这是真的,但实际应用程序将取决于您当前的模式,有多少层,缓存和配置)。

更新:扩展了一下,删除了一些含糊之处

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM