NHibernate ISession刷新:何时何地使用它,为什么?
让我彻底困惑的事情之一是使用session.Flush
,与session.Commit
和session.Close
一起使用。
有时session.Close
起作用,例如它提交我需要的所有更改。 我知道当我有一个事务时,我需要使用提交,或者有几个创build/更新/删除的工作单元,这样,如果发生错误,我可以select回滚。
但是有时候我真的被session.Flush
背后的逻辑所session.Flush
。 我已经看到你有一个session.SaveOrUpdate()
其次是一个刷新的例子,但是当我删除刷新它工作正常。 有时候我在Flush语句中遇到错误,说会话超时,删除它确保我没有遇到那个错误。
有没有人有一个很好的指导方针,以何时何地使用同花顺? 我已经检查了这个NHibernate文档,但我仍然无法find一个简单的答案。
简述:
- 始终使用交易
- 不要使用
Close()
,而是将你的调用包装在using
语句的ISession
或者在其他地方pipe理你的ISession的生命周期 。
从文档 :
有时,
ISession
将执行将ADO.NET连接状态与内存中的对象状态同步所需的SQL语句。 这个过程,刷新,默认情况下发生在以下几点
- 从
Find()
或Enumerable()
一些调用中,- 从
NHibernate.ITransaction.Commit()
- 来自
ISession.Flush()
SQL语句按以下顺序发布
- 所有的实体插入,以相同的顺序使用
ISession.Save()
保存相应的对象- 所有实体更新
- 所有collections删除
- 所有集合元素的删除,更新和插入
- 所有集合插入
- 所有的实体删除,以相同的顺序相应的对象被删除使用
ISession.Delete()
(使用本地ID生成的对象在保存时会插入一个例外)。
除非你明确
Flush()
,否则绝对不能保证Session何时执行ADO.NET调用,只有执行它们的顺序 。 但是,NHibernate确保ISession.Find(..)
方法永远不会返回陈旧的数据; 也不会返回错误的数据。可以更改默认行为,以便更频繁地进行刷新。
FlushMode
类定义了三种不同的模式:只在提交时刷新(只有在使用NHibernateITransaction
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()防止我的错误发生。