.net NHibernate ISession Flush:何时何地使用它,为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NHibernate ISession Flush: Where and when to use it, and why?
提问by Jon Limjap
One of the things that get me thoroughly confused is the use of session.Flush,in conjunction with session.Commit, and session.Close.
让我彻底困惑的一件事是使用session.Flush, 结合session.Commit, 和session.Close。
Sometimes session.Closeworks, e.g., it commits all the changes that I need. I know I need to use commit when I have a transaction, or a unit of work with several creates/updates/deletes, so that I can choose to rollback if an error occurs.
有时session.Close有效,例如,它提交我需要的所有更改。我知道当我有一个事务或一个具有多个创建/更新/删除的工作单元时,我需要使用提交,这样我就可以在发生错误时选择回滚。
But sometimes I really get stymied by the logic behind session.Flush. I have seen examples where you have a session.SaveOrUpdate()followed by a flush, but when I remove Flush it works fine anyway. Sometimes I run into errors on the Flush statement saying that the session timed out, and removing it made sure that I didn't run into that error.
但有时我真的被背后的逻辑所困扰session.Flush。我见过一些例子,你有一个session.SaveOrUpdate()紧随其后的冲洗,但是当我删除冲洗时,它仍然可以正常工作。有时我在 Flush 语句中遇到错误,说会话超时,删除它确保我没有遇到那个错误。
Does anyone have a good guideline as to where or when to use a Flush? I've checked out the NHibernate documentation for this, but I still can't find a straightforward answer.
有没有人有关于在何处或何时使用 Flush 的良好指南?我已经为此查看了 NHibernate 文档,但我仍然找不到直接的答案。
回答by Matt Hinze
Briefly:
简要地:
- Always use transactions
- Don't use
Close(), instead wrap your calls on anISessioninside ausingstatement or manage the lifecycle of your ISession somewhere else.
- 始终使用事务
- 不要使用
Close(),而是将您的调用包装ISession在using语句内部或在其他地方管理您的 ISession 的生命周期。
From the documentation:
从文档:
From time to time the
ISessionwill execute the SQL statements needed to synchronize the ADO.NET connection's state with the state of objects held in memory. This process, flush, occurs by default at the following points
- from some invocations of
Find()orEnumerable()- from
NHibernate.ITransaction.Commit()- from
ISession.Flush()The SQL statements are issued in the following order
- all entity insertions, in the same order the corresponding objects were saved using
ISession.Save()- all entity updates
- all collection deletions
- all collection element deletions, updates and insertions
- all collection insertions
- all entity deletions, in the same order the corresponding objects were deleted using
ISession.Delete()(An exception is that objects using native ID generation are inserted when they are saved.)
Except when you explicity
Flush(), there are absolutely no guarantees about when the Session executes the ADO.NET calls, only the order in which they are executed. However, NHibernate does guarantee that theISession.Find(..)methods will never return stale data; nor will they return the wrong data.It is possible to change the default behavior so that flush occurs less frequently. The
FlushModeclass defines three different modes: only flush at commit time (and only when the NHibernateITransactionAPI is used), flush automatically using the explained routine, or never flush unlessFlush()is called explicitly. The last mode is useful for long running units of work, where anISessionis kept open and disconnected for a long time.
有时
ISession会执行将 ADO.NET 连接的状态与内存中保存的对象的状态同步所需的 SQL 语句。这个过程,flush,默认发生在以下几点
- 从某些调用
Find()或Enumerable()- 从
NHibernate.ITransaction.Commit()- 从
ISession.Flush()SQL 语句按以下顺序发出
- 所有实体插入,以相同的顺序保存相应的对象
ISession.Save()- 所有实体更新
- 所有集合删除
- 所有集合元素删除、更新和插入
- 所有集合插入
- 所有实体删除,以相同的顺序删除相应的对象
ISession.Delete()(一个例外是使用本机 ID 生成的对象在保存时被插入。)
除非您明确指出
Flush(),否则绝对不能保证 Session 何时执行 ADO.NET 调用,只能保证它们的执行顺序。然而,NHibernate 确实保证这些ISession.Find(..)方法永远不会返回陈旧的数据;他们也不会返回错误的数据。可以更改默认行为,以便减少刷新发生的频率。的
FlushMode类定义了三种不同的模式:仅在提交时齐平(以及NHibernate的,只有当ITransaction使用API),自动冲水使用解释程序中,或从未冲洗除非Flush()显式调用。最后一种模式对于长时间运行的工作单元很有用,其中 anISession长时间保持打开和断开连接。
...
...
Also refer to this section:
另请参阅本节:
Ending a session involves four distinct phases:
- flush the session
- commit the transaction
- close the session
- handle exceptions
Flushing the Session
If you happen to be using the
ITransactionAPI, you don't need to worry about this step. It will be performed implicitly when the transaction is committed. Otherwise you should callISession.Flush()to ensure that all changes are synchronized with the database.Committing the database transaction
If you are using the NHibernate ITransaction API, this looks like:
tx.Commit(); // flush the session and commit the transactionIf you are managing ADO.NET transactions yourself you should manually
Commit()the ADO.NET transaction.sess.Flush(); currentTransaction.Commit();If you decide not to commit your changes:
tx.Rollback(); // rollback the transactionor:
currentTransaction.Rollback();If you rollback the transaction you should immediately close and discard the current session to ensure that NHibernate's internal state is consistent.
Closing the ISession
A call to
ISession.Close()marks the end of a session. The main implication of Close() is that the ADO.NET connection will be relinquished by the session.tx.Commit(); sess.Close(); sess.Flush(); currentTransaction.Commit(); sess.Close();If you provided your own connection,
Close()returns a reference to it, so you can manually close it or return it to the pool. OtherwiseClose()returns it to the pool.
结束会话涉及四个不同的阶段:
- 刷新会话
- 提交交易
- 关闭会话
- 处理异常
刷新会话
如果您碰巧正在使用
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()将其返回到池中。
回答by Sean Carpenter
Starting in NHibernate 2.0, transactions are required for DB operations. Therefore, the ITransaction.Commit()call will handle any necessary flushing. If for some reason you aren't using NHibernate transactions, then there will be no auto-flushing of the session.
从 NHibernate 2.0 开始,数据库操作需要事务。因此,该ITransaction.Commit()调用将处理任何必要的刷新。如果由于某种原因您没有使用 NHibernate 事务,那么会话将不会自动刷新。
回答by Sean Carpenter
From time to time the ISession will execute the SQL statements needed to synchronize the ADO.NET connection's state with the state of objects held in memory.
ISession 会不时执行将 ADO.NET 连接的状态与内存中保存的对象的状态同步所需的 SQL 语句。
And always use
并始终使用
using (var transaction = session.BeginTransaction())
{
transaction.Commit();
}
after the changes are committed than this changes to save into database we use transaction.Commit();
提交更改后,将更改保存到数据库中,我们使用 transaction.Commit();
回答by Paul T Davies
Here are two examples of my code where it would fail without session.Flush():
以下是我的代码的两个示例,如果没有 session.Flush(),它会失败:
http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html
http://www.lucidcoding.blogspot.co.uk/2012/05/changed-type-of-entity-persistence.html
at the end of this, you can see a section of code where I set identity insert on, save the entity then flush, then set identity insert off. Without this flush it seemed to be setting identity insert on and off then saving the entity.
最后,您可以看到一段代码,我将身份插入设置为打开,保存实体然后刷新,然后将身份插入设置为关闭。如果没有这个刷新,它似乎是打开和关闭身份插入,然后保存实体。
The use of Flush() gave me more control over what was going on.
Flush() 的使用让我可以更好地控制正在发生的事情。
Here is another example:
这是另一个例子:
Sending NServiceBus message inside TransactionScope
在 TransactionScope 内发送 NServiceBus 消息
I don't fully understand why on this one, but Flush() prevented my error from happening.
我不完全理解为什么会出现这种情况,但 Flush() 阻止了我的错误发生。

