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

发布于 2024-07-04 22:08:56 字数 482 浏览 5 评论 0原文

让我彻底困惑的事情之一是使用 session.Flushsession.Commitsession.Close 结合使用。

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

但有时我真的会被 session.Flush 背后的逻辑所困扰。 我见过一些例子,其中有一个 session.SaveOrUpdate() 后跟一个刷新,但是当我删除 Flush 时它仍然可以正常工作。 有时,我在 Flush 语句上遇到错误,指出会话超时,删除它可以确保我没有遇到该错误。

有人对何时何地使用冲水有好的指导吗? 我已经查看了 NHibernate 文档,但仍然找不到简单的答案。

One of the things that get me thoroughly confused is the use of session.Flush,in conjunction with session.Commit, and session.Close.

Sometimes session.Close works, 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.

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一花一树开 2024-07-11 22:08:56

以下是我的代码的两个示例,如果没有 session.Flush(),它将失败:

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

在此结束时,您可以看到一段代码,我在其中设置身份插入,保存实体然后刷新,然后设置身份插入关闭。 如果没有这种刷新,它似乎会设置身份插入打开和关闭,然后保存实体。

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

这是另一个示例:

在 TransactionScope 内发送 NServiceBus 消息

我不完全明白为什么这个,但是 Flush() 阻止了我的错误发生。

Here are two examples of my code where it would fail without session.Flush():

http://www.lucidcoding.blogspot.co.uk/2012/05/changing-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.

Here is another example:

Sending NServiceBus message inside TransactionScope

I don't fully understand why on this one, but Flush() prevented my error from happening.

北斗星光 2024-07-11 22:08:56

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

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.

不念旧人 2024-07-11 22:08:56

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

并且始终在提交更改后使用

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

,而不是将此更改保存到数据库中,我们使用 transaction.Commit();

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.

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();

春花秋月 2024-07-11 22:08:56

简而言之:

  1. 始终使用事务
  2. 不要使用 Close(),而是将调用包装在 using 语句或 ma​​nage 内的 ISession 上你的 ISession 的生命周期在其他地方

来自文档

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

  • 来自 Find()Enumerable() 的某些调用
  • 来自NHibernate.ITransaction.Commit()
  • 来自ISession.Flush()

SQL语句按以下顺序发出

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

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

除非您显式地Flush(),否则绝对不能保证会话何时执行 ADO.NET 调用,只能保证它们的执行顺序。 然而,NHibernate 确实保证 ISession.Find(..) 方法永远不会返回过时的数据; 他们也不会返回错误的数据。

可以更改默认行为,以便减少刷新发生的频率。 FlushMode 类定义了三种不同的模式:仅在提交时刷新(并且仅当使用 NHibernate ITransaction API 时)、使用解释的例程自动刷新,或者从不刷新,除非Flush() 被显式调用。 最后一种模式对于长时间运行的工作单元很有用,其中 ISession 长时间保持打开和断开连接。

...

另请参阅本节

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

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

刷新会话

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

提交数据库事务

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

tx.Commit();   // 刷新会话并提交事务 
  

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

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

如果您决定不提交更改:

tx.Rollback();   // 回滚事务 
  

或者:

currentTransaction.Rollback(); 
  

如果回滚事务,您应该立即关闭并丢弃当前会话,以确保 NHibernate 的内部状态一致。

关闭 ISession

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

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

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

如果您提供了自己的连接,Close() 返回对其的引用,因此您可以手动关闭它或将其返回到池中。 否则 Close() 将其返回到池中。

Briefly:

  1. Always use transactions
  2. Don't use Close(), instead wrap your calls on an ISession inside a using statement or manage the lifecycle of your ISession somewhere else.

From the documentation:

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. This process, flush, occurs by default at the following points

  • from some invocations of Find() or Enumerable()
  • from NHibernate.ITransaction.Commit()
  • from ISession.Flush()

The SQL statements are issued in the following order

  1. all entity insertions, in the same order the corresponding objects were saved using ISession.Save()
  2. all entity updates
  3. all collection deletions
  4. all collection element deletions, updates and insertions
  5. all collection insertions
  6. 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 the ISession.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 FlushMode class defines three different modes: only flush at commit time (and only when the NHibernate ITransaction API is used), flush automatically using the explained routine, or never flush unless Flush() is called explicitly. The last mode is useful for long running units of work, where an ISession is kept open and disconnected for a long time.

...

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 ITransaction API, you don't need to worry about this step. It will be performed implicitly when the transaction is committed. Otherwise you should call ISession.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 transaction

If 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 transaction

or:

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. Otherwise Close() returns it to the pool.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文