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

时间:2008-09-04 08:04:04

标签: .net session nhibernate flush

令我彻底混淆的一件事是使用session.Flush,与session.Commitsession.Close一起使用。

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

但有时我真的被session.Flush背后的逻辑所困扰。我见过一些例子,你有一个session.SaveOrUpdate()后跟一个同花顺,但是当我删除Flush时它无论如何都能正常工作。有时我在Flush语句中遇到错误,说会话超时,并删除它确保我没有遇到该错误。

有没有人对何时何地使用同花顺有一个很好的指导方针?我已经检查了NHibernate文档,但我仍然找不到简单的答案。

4 个答案:

答案 0 :(得分:233)

简言之:

  1. 始终使用交易
  2. 请勿使用Close(),而是将您的电话打包到ISession语句中的using管理其他地方的ISession生命周期。< / LI>

    来自the documentation

      

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

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

    SQL语句按以下顺序发布

         
        
    1. 所有实体插入,使用ISession.Save()
    2. 以相同的顺序保存相应的对象   
    3. 所有实体更新
    4.   
    5. 所有集合删除
    6.   
    7. 所有集合元素删除,更新和插入
    8.   
    9. 所有收集插入
    10.   
    11. 所有实体删除,使用ISession.Delete()
    12. 以相同的顺序删除相应的对象         

      (例外情况是,保存时会插入使用本机ID生成的对象。)

           

      除非您明确Flush(),否则绝对无法保证Session何时执行ADO.NET调用,只保证执行它们的顺序。但是,NHibernate确保ISession.Find(..)方法永远不会返回陈旧数据;他们也不会返回错误的数据。

           

      可以更改默认行为,以便更频繁地进行刷新。 FlushMode类定义了三种不同的模式:仅在提交时刷新(并且仅在使用NHibernate ITransaction 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()阻止了我的错误发生。