189

让我彻底困惑的一件事是, 与和session.Flush结合使用。session.Commitsession.Close

有时session.Close有效,例如,它提交了我需要的所有更改。我知道当我有一个事务或一个具有多个创建/更新/删除的工作单元时我需要使用提交,以便在发生错误时我可以选择回滚。

但有时我真的被背后的逻辑所阻碍session.Flush。我见过一些例子,你有一个session.SaveOrUpdate()后跟冲洗,但是当我删除冲洗它无论如何都可以正常工作。有时我在 Flush 语句中遇到错误,说会话超时,删除它确保我没有遇到该错误。

有没有人对何时何地使用 Flush 有很好的指导?我已经为此检查了 NHibernate 文档,但我仍然找不到一个简单的答案。

4

4 回答 4

238

简要地:

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

文档中

将不时ISession执行将 ADO.NET 连接状态与内存中保存的对象状态同步所需的 SQL 语句。这个过程,flush,默认发生在以下几点

  • 从某些调用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 ITransactionAPI 时),使用解释的例程自动刷新,或从不刷新,除非Flush()显式调用。最后一种模式对于长时间运行的工作单元很有用,其中 anISession长时间保持打开和断开连接。

...

另请参阅本节

结束会话涉及四个不同的阶段:

  • 刷新会话
  • 提交事务
  • 关闭会话
  • 处理异常

刷新会话

如果您恰好使用ITransactionAPI,则无需担心此步骤。它会在事务提交时隐式执行。否则,您应该调用ISession.Flush()以确保所有更改都与数据库同步。

提交数据库事务

如果您使用的是 NHibernate ITransaction API,则如下所示:

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

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

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

如果您决定不提交更改:

tx.Rollback();  // rollback the transaction

或者:

currentTransaction.Rollback();

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

关闭 ISession

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

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

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

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

于 2008-09-04T11:58:27.247 回答
14

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

于 2008-09-04T17:17:08.837 回答
1

有时,ISession 会执行同步 ADO.NET 连接状态与内存中对象状态所需的 SQL 语句。

并始终使用

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

提交更改后,将更改保存到数据库中,我们使用 transaction.Commit();

于 2014-03-05T09:25:26.057 回答
0

这是我的代码的两个示例,如果没有 session.Flush(),它将失败:

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

在此结束时,您可以看到一段代码,其中我设置了身份插入,保存实体然后刷新,然后设置身份插入关闭。如果没有这个刷新,它似乎是在打开和关闭身份插入,然后保存实体。

Flush() 的使用让我可以更好地控制正在发生的事情。

这是另一个例子:

在 TransactionScope 内发送 NServiceBus 消息

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

于 2012-11-06T13:38:48.130 回答