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

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

有时session.Close起作用,例如它提交我需要的所有更改。 我知道当我有一个事务时,我需要使用提交,或者有几个创build/更新/删除的工作单元,这样,如果发生错误,我可以select回滚。

但是有时候我真的被session.Flush背后的逻辑所session.Flush 。 我已经看到你有一个session.SaveOrUpdate()其次是一个刷新的例子,但是当我删除刷新它工作正常。 有时候我在Flush语句中遇到错误,说会话超时,删除它确保我没有遇到那个错误。

有没有人有一个很好的指导方针,以何时何地使用同花顺? 我已经检查了这个NHibernate文档,但我仍然无法find一个简单的答案。

简述:

  1. 始终使用交易
  2. 不要使用Close() ,而是将你的调用包装在using语句的ISession或者在其他地方pipe理你的ISession的生命周期

从文档 :

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

  • Find()Enumerable()一些调用中,
  • NHibernate.ITransaction.Commit()
  • 来自ISession.Flush()

SQL语句按以下顺序发布

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

(使用本地ID生成的对象在保存时会插入一个例外)。

除非你明确Flush() ,否则绝对不能保证Session何时执行ADO.NET调用,只有执行它们的顺序 。 但是,NHibernate确保ISession.Find(..)方法永远不会返回陈旧的数据; 也不会返回错误的数据。

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

另请参阅本节 :

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

  • 刷新会话
  • 提交交易
  • closures会议
  • 处理exception

冲洗会议

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

提交数据库事务

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

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

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

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

如果您决定不提交更改:

 tx.Rollback(); // rollback the transaction 

要么:

 currentTransaction.Rollback(); 

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

closuresISession

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

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

如果您提供了自己的连接,则Close()将返回对其的引用,以便您可以手动closures它或将其返回到池中。 否则, 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

在这个结尾,你可以看到我设置身份插入的一段代码,保存实体然后刷新,然后设置身份插入。 没有这个刷新,似乎是设置身份插入和closures,然后保存该实体。

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

这是另一个例子:

在TransactionScope中发送NServiceBus消息

我不完全明白为什么在这一个,但Flush()防止我的错误发生。