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


187

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

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

但是有时候我确实被背后的逻辑所束缚session.Flush。我看过一些例子,其中有一个session.SaveOrUpdate()后跟冲洗功能,但是当我删除“冲洗”功能后,它仍然可以正常工作。有时,我在Flush语句上遇到错误,说会话超时,将其删除可以确保我没有遇到该错误。

是否有人在哪里或何时使用同花顺有很好的指导原则?我已经检查了NHibernate文档,但是仍然找不到简单的答案。

Answers:


236

简要地:

  1. 一律使用交易
  2. 不要使用Close(),而是将调用包装ISessionusing语句内部或在其他地方管理ISession的生命周期

文档中

有时ISession会执行将ADO.NET连接状态与内存中保存的对象状态同步所需的SQL语句。默认情况下,此过程在以下几点进行刷新

  • 来自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情况下,an 会长时间保持打开和断开状态。

...

另请参阅本节

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

  • 刷新会话
  • 提交交易
  • 关闭会议
  • 处理异常

冲洗会议

如果您恰好在使用ITransactionAPI,则无需担心此步骤。提交事务时将隐式执行该操作。否则,您应该致电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()将其返回到池中。


2
对我来说,这行很关键:“ Close()的主要含义是会话将放弃ADO.NET连接。” 如果不调用ISession.Close(),则连接将被填满,直到获得数据库超时为止。:o
戴夫·蒂本

我们通常:打开会话session.BeginTransaction()工作... session.Transaction.Commit()session.BeginTransaction()工作... session.Transaction.Commit()session.BeginTransaction()工作.. session.Transaction.Commit ()配置会话。
敏捷绝地

出色的记录和+1等-但是我认为可能需要进行编辑,因为您在顶部说“永不关闭”,然后再说“如果回滚事务,您应该立即关闭并丢弃当前会话”
SpaceBison

可以更改SQL语句的顺序。我的意思是我需要对一个实体对象执行更新,而不是插入,因为我在相应的表中有一个约束。
bob_saginowski

14

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


1

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

并始终使用

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

提交更改之后,会将更改保存到数据库中,然后使用transaction.Commit();。


0

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

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

最后,您可以看到一段代码,其中我设置了身份插入,保存实体然后刷新,然后将身份插入关闭。没有这种冲洗,似乎是在打开和关闭标识插入,然后保存实体。

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

这是另一个示例:

在TransactionScope内发送NServiceBus消息

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.