我已经阅读了有关为什么强烈建议在NH中使用读取操作的事务的文档和说明。但是,我还没有完全“买进”它。有人可以试着解释它而不只是告诉我RTFM,我已经做过了吗? ;)
答案 0 :(得分:24)
This post from one of the authors可能有你的答案:
即使我们只是阅读数据,我们也是 想要使用交易,因为 使用交易确保我们得到 数据库的一致结果。 NHibernate假设所有访问权限 数据库是在a下完成的 交易,强烈反对 没有使用会话的任何使用 事务。
暂且不谈安全问题 处理交易, 假设交易是 昂贵的,我们需要优化它们 一个假的。如前所述, 数据库总是在运行 交易。数据库已经存在 经过大量优化可以使用 交易。问题是什么 这是每个声明或每批次。 有一些工作需要 要做的是创造和处置一个 交易,并且必须按此进行 声明实际上比成本更高 每批做一次。
答案 1 :(得分:8)
其他人所说的是真的,但是他们没有指出不自己控制交易的问题是如果你在没有明确交易的情况下执行几个NHibernate操作,那么每个操作都将在中进行。单独交易。
因此,您很容易在操作之间出现不一致。通过显式启动NHibernate事务然后执行其中的操作,可以保证这些操作的一致性。
当然,对于任何隐式启动事务的数据访问层,如果不这样做,这是正确的。它不仅限于NHibernate。
答案 2 :(得分:6)
var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);
如果某个其他事务在两个查询之间从Bar中删除行,该怎么办?您将遇到幻像数据问题。这不是NHibernate的具体问题。在不使用事务的情况下,您将遇到与任何其他类型的数据库访问相同的问题。您应该阅读有关交易的手册,而不是NHiberante手册。
答案 3 :(得分:5)
让我们关注如果您不使用交易会发生什么。在处理结束时,但在开始读取数据(即视图)之前关闭Session是习惯的,但不是强制性的。此方法在术语“Open Session in View”下传播(尽管它显然具有防止在关闭之前读取的模式)。此模式通常用于Web应用程序,其中会话在请求到达时打开,并在写入响应流之前关闭。
(N)Hibernate需要会话和事务。当您在不使用显式交易的情况下阅读时,将为您设置交易。在提交事务后读取时,行为取决于NH配置和驱动程序。
ODBC和JDBC都没有定义连接关闭时发生的情况以及未提交或未返回的数据。重新打开连接后,可能会自动启动新事务。
使用非事务性访问只能与NHibernate配置中显式设置auto-commit
一起使用。如果没有,则使用驱动程序的默认值,它可能有效,或者可能无效。
简而言之,当您不在读取上使用事务时,存在许多缺点和未定义的行为。它会经常工作,但这取决于配置,应用的模式,驱动程序。您很有可能获得LazyInitializationException
s,这是在提交后读取而不打开新事务的常见结果。
“最佳实践”是将一个事务用于读/写,另一个事务用于只读。这在前面的链接“我可以在会话中使用两个事务”部分进行了简要描述,但需要更多的实现。
它不仅是“使用事务进行读取”,它还是:“使用您用于写入的相同事务进行读取”。 (然后,虽然这是真的,但实际的应用程序将取决于您当前的模式,有多少层,缓存和配置。)
更新扩展了一点,删除了一些含糊之处
答案 4 :(得分:3)