NHibernate ISession Flush: 何时何地使用它,为什么?

使我彻底困惑的事情之一是 session.Flush的使用,与 session.Commitsession.Close一起使用。

有时 session.Close可以工作,例如,它提交我需要的所有更改。我知道当我有一个事务,或者一个工作单元有几个创建/更新/删除时,我需要使用提交,这样我就可以在出现错误时选择回滚。

但有时我真的被 session.Flush背后的逻辑所阻碍。我看到的例子,你有一个 session.SaveOrUpdate()后面一个刷新,但是当我删除刷新工程罚款无论如何。有时我在 Flush 语句中遇到错误,说会话超时了,删除它可以确保我没有遇到这个错误。

有没有人有一个好的指南,关于何时何地使用同花顺?我已经查看了 NHibernate 的文档,但仍然找不到一个直截了当的答案。

81394 次浏览

简要介绍:

  1. 始终使用事务
  2. 不要使用 Close(),而是将调用包装在 using语句或 在其他地方管理您的 ISsession 的生命周期中的 ISession上。

来自 文件:

ISession将不时地执行 SQL 语句,以便将 ADO.NET 连接的状态与内存中持有的对象的状态同步。此进程(刷新)默认情况下在以下几点发生

  • Find()Enumerable()的某些调用
  • NHibernate.ITransaction.Commit()
  • ISession.Flush()

SQL 语句按以下顺序发出

  1. 所有实体插入,以相同的顺序使用 ISession.Save()保存对应的对象
  2. 所有实体更新
  3. 所有集合删除
  4. 所有集合元素的删除、更新和插入
  5. 所有集合插入
  6. 所有的实体删除,使用 ISession.Delete()以相同的顺序删除相应的对象

(使用本机 ID 生成的对象在保存时插入,这是一个例外。)

除了显式 Flush()之外,绝对不能保证 Session 何时执行 ADO.NET 调用,只能保证它们的执行顺序 。然而,NHibernate 确实保证了 ISession.Find(..)方法永远不会返回过时的数据; 它们也不会返回错误的数据。

可以更改默认行为,以减少刷新发生的频率。FlushMode类定义了三种不同的模式: 只在提交时刷新(并且只在使用 NHibernate ITransaction API 时) ,使用解释的例程自动刷新,或者除非显式调用 Flush(),否则永远不刷新。最后一种模式对于长时间运行的工作单元非常有用,在这种情况下,ISession保持打开状态并长时间断开连接。

...

此外,请参阅 这部分:

会议的结束包括四个不同的阶段:

  • 冲洗会话
  • 提交交易
  • 结束会议
  • 处理异常

冲洗会议

如果您正好使用的是 ITransaction API,那么不必担心这一步。当事务被提交时,它将被隐式执行。否则,应该调用 ISession.Flush()以确保所有更改都与数据库同步。

提交数据库事务

如果您正在使用 NHibernate ITransaction API,那么这看起来像:

tx.Commit(); // flush the session and commit the transaction

如果您自己管理 ADO.NET 事务,则应该手动 Commit() ADO.NET 事务。

sess.Flush();
currentTransaction.Commit();

如果您决定不提交更改:

tx.Rollback();  // rollback the transaction

或:

currentTransaction.Rollback();

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

关闭 ISsession

ISession.Close()的调用标志着会话的结束。Close ()的主要含义是会话将放弃 ADO.NET 连接。

tx.Commit();
sess.Close();


sess.Flush();
currentTransaction.Commit();
sess.Close();

如果您提供了自己的连接,Close()将返回对它的引用,因此您可以手动关闭它或将它返回到池中。否则 Close()将它返回到池中。

从 NHibernate 2.0开始,DB 操作需要事务。因此,ITransaction.Commit()调用将处理任何必要的冲洗。如果由于某种原因您没有使用 NHibernate 事务,那么将不会自动刷新会话。

这里有两个例子,我的代码如果没有会话就会失败。 Flush () :

Http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html

在本文的末尾,您可以看到一段代码,其中我设置了标识插入,保存实体然后刷新,然后设置标识插入关闭。没有这个刷新,它似乎是设置身份插入和关闭,然后保存实体。

Flush ()的使用让我对正在发生的事情有了更多的控制。

下面是另一个例子:

在 TransactionScope 中发送 NServiceBus 消息

我不完全理解为什么在这个问题上,但是 Flush ()阻止了我的错误的发生。

ISsession 会不时地执行 SQL 语句,以便将 ADO.NET 连接的状态与内存中持有的对象的状态同步。

并且一直使用

 using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}

在提交更改之后,我们使用事务处理将这些更改保存到数据库中