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

时间:2020-03-05 18:47:29  来源:igfitidea点击:

使我彻底困惑的一件事是结合使用session.Flush和session.Commit和session.Close。

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

但是有时候我真的会被session.Flush背后的逻辑所困扰。我已经看到了一些示例,其中有一个session.SaveOrUpdate()然后进行刷新,但是当我删除Flush时,它仍然可以正常工作。有时,我在Flush语句上遇到错误,说会话超时,将其删除会确保我没有遇到该错误。

是否有人在哪里或者何时使用同花顺有很好的指导原则?我已经检查了NHibernate文档,但是仍然找不到简单的答案。

解决方案

回答

简要地:

  • 一律使用交易
  • 不要使用Close(),而是将调用包装在using语句中的ISession上,或者在其他地方管理ISession的生命周期。

从文档中:

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
  
  
  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 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.

...

另请参阅本节:

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.

回答

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