C# 读取上的NHibernate事务

C# 读取上的NHibernate事务,c#,nhibernate,transactions,C#,Nhibernate,Transactions,我已经阅读了文档并解释了为什么强烈建议在NH的读取操作中使用事务。然而,我还没有完全“相信”它。有人能试着解释一下,而不只是告诉我RTFM,我已经这么做了吗?;) 如果其他事务从两个查询之间的Bar中删除行,该怎么办?您将遇到幻象数据问题。这不是NHibernate的具体问题。在不使用事务的情况下,任何其他类型的数据库访问都会遇到同样的问题。您应该阅读关于一般交易的手册,而不是NHiberante手册。可能会有您的答案: 即使我们只是在读取数据,我们也会 要使用事务,因为 使用事务确保我们得到

我已经阅读了文档并解释了为什么强烈建议在NH的读取操作中使用事务。然而,我还没有完全“相信”它。有人能试着解释一下,而不只是告诉我RTFM,我已经这么做了吗?;)

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

可能会有您的答案:

即使我们只是在读取数据,我们也会 要使用事务,因为 使用事务确保我们得到 来自数据库的一致结果。 NHibernate假设所有访问 数据库是在 交易,强烈劝阻 未经授权的会话的任何使用 交易

撇开汽车的安全问题不谈 处理事务时 假设交易是 成本高昂,我们需要对其进行优化 假的。如前所述, 数据库总是在运行 交易而且数据库已经被更新 进行了大量优化,可用于 交易。问题是无论如何 这是每个语句或每个批。 需要做一些工作 创建和处置 交易,并且必须按照 声明的成本实际上比 每批做一次


其他人所说的是正确的,但他们没有指出不自己控制事务的问题是,如果您在没有显式事务的情况下执行多个NHibernate操作,那么这些操作中的每一个都将在独立的事务中进行

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

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

还有:

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

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

ODBC和JDBC都没有定义当连接关闭并且存在未提交或未回滚的数据时会发生什么。重新打开连接时,可能会自动启动新事务

使用非事务性访问只能与在NHibernate配置中显式设置
自动提交
一起使用。如果没有,则使用默认的驱动程序,它可能工作,也可能不工作

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

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

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


更新:进行了一些扩展,消除了一些歧义

您说:“最佳做法”是使用一个事务进行读/写,另一个事务进行只读。”然后您说:“使用您用于写的同一事务进行读”这是一个打字错误吗?@DmytroLaptin,如果您只在阅读,请使用事务,如果在一个数据集中读写数据,请使用事务,但如果同时执行这两个操作,请使用相同的事务。虽然这是5.5年前写的,但我相信我想表达的观点是,即使使用只读数据,也要使用事务。所以不,我认为这不是打字错误,这两句话互相补充。
var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);