让我彻底困惑的事情之一是使用 session.Flush,和这个结合 session.Commit, , 和 session.Close.

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

但有时我真的被背后的逻辑所困扰 session.Flush. 。我见过一些例子,你有一个 session.SaveOrUpdate() 然后是冲洗,但是当我删除冲洗时它仍然可以正常工作。有时,我在 Flush 语句上遇到错误,指出会话超时,删除它可以确保我没有遇到该错误。

有人对何时何地使用冲水有好的指导吗?我已经查看了 NHibernate 文档,但仍然找不到简单的答案。

有帮助吗?

解决方案

简要地:

  1. 始终使用交易
  2. 不要使用 Close(), ,而是将您的呼叫包装在 ISession 里面一个 using 声明或 在其他地方管理 ISession 的生命周期.

文档:

时不时地 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 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 的内部状态一致。

关闭 ISession

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

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

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

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

其他提示

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

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

并且始终使用

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

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

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

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

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

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

这是另一个例子:

在 TransactionScope 内发送 NServiceBus 消息

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top