令我彻底混淆的一件事是使用session.Flush
,与session.Commit
和session.Close
一起使用。
有时session.Close
有效,例如,它会提交我需要的所有更改。我知道我需要在有事务时使用提交,或者需要使用多个创建/更新/删除的工作单元,这样我就可以选择在发生错误时回滚。
但有时我真的被session.Flush
背后的逻辑所困扰。我见过一些例子,你有一个session.SaveOrUpdate()
后跟一个同花顺,但是当我删除Flush时它无论如何都能正常工作。有时我在Flush语句中遇到错误,说会话超时,并删除它确保我没有遇到该错误。
有没有人对何时何地使用同花顺有一个很好的指导方针?我已经检查了NHibernate文档,但我仍然找不到简单的答案。
答案 0 :(得分:233)
简言之:
Close()
,而是将您的电话打包到ISession
语句中的using
或管理其他地方的ISession生命周期。< / LI>
醇>
ISession
会不时执行将ADO.NET连接状态与内存中保存的对象状态同步所需的SQL语句。默认情况下,此过程刷新,发生在以下几点
- 来自
的某些调用Find()
或Enumerable()
- 来自
NHibernate.ITransaction.Commit()
- 来自
ISession.Flush()
SQL语句按以下顺序发布
- 所有实体插入,使用
以相同的顺序保存相应的对象ISession.Save()
- 所有实体更新
- 所有集合删除
- 所有集合元素删除,更新和插入
- 所有收集插入
- 所有实体删除,使用
以相同的顺序删除相应的对象 醇>ISession.Delete()
(例外情况是,保存时会插入使用本机ID生成的对象。)
除非您明确
Flush()
,否则绝对无法保证Session何时执行ADO.NET调用,只保证执行它们的顺序。但是,NHibernate确保ISession.Find(..)
方法永远不会返回陈旧数据;他们也不会返回错误的数据。可以更改默认行为,以便更频繁地进行刷新。
FlushMode
类定义了三种不同的模式:仅在提交时刷新(并且仅在使用NHibernateITransaction
API时),使用解释的例程自动刷新,或者从不刷新,除非Flush()
是明确地叫。最后一种模式对于长时间运行的工作单元非常有用,其中ISession
保持打开状态并长时间断开连接。
...
另请参阅this section:
结束会议涉及四个不同的阶段:
- 刷新会话
- 提交交易
- 关闭会话
- 处理例外
刷新会话
如果您恰好使用
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()
将其返回池中。
答案 1 :(得分:14)
从NHibernate 2.0开始,数据库操作需要事务处理。因此,ITransaction.Commit()
调用将处理任何必要的刷新。如果由于某种原因你没有使用NHibernate事务,那么就不会自动刷新会话。
答案 2 :(得分:1)
ISession将不时执行将ADO.NET连接状态与内存中保存的对象状态同步所需的SQL语句。
始终使用
using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}
提交更改后,将更改保存到数据库中,我们使用transaction.Commit();
答案 3 :(得分:0)
以下是我的代码的两个示例,如果没有session.Flush():
,它将失败http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html
在这结束时,您可以看到我设置标识插入的代码部分,保存实体然后刷新,然后设置标识插入关闭。如果没有这个刷新,它似乎是设置身份插入打开和关闭然后保存实体。
使用Flush()让我可以更好地控制正在发生的事情。
这是另一个例子:
Sending NServiceBus message inside TransactionScope
我不完全理解为什么在这个上,但Flush()阻止了我的错误发生。