NHibernate和保存存在问题-NHibernate未检测到更改并使用旧值

NHibernate和保存存在问题-NHibernate未检测到更改并使用旧值,nhibernate,hibernate,Nhibernate,Hibernate,当我这样做时: Cat x = Session.Load<Cat>(123); x.Name = "fritz"; Session.Flush(); Cat x = new Cat(); Session.Save(x); x.Name = "fritz"; Session.Flush(); 我的name为NULL,因为调用Session.Save时就是这样。为什么NHibernate没有检测到这些变化——或者更好的是,在刷新时获取INSERT语句的值 添加:澄清:Session.

当我这样做时:

Cat x = Session.Load<Cat>(123);
x.Name = "fritz";
Session.Flush();
Cat x = new Cat();
Session.Save(x);
x.Name = "fritz";
Session.Flush();
我的name为NULL,因为调用Session.Save时就是这样。为什么NHibernate没有检测到这些变化——或者更好的是,在刷新时获取INSERT语句的值

添加:澄清:Session.FlushMode设置为None,因此在我这么说之前不会自动刷新。我还在GUID.comb生成器中使用GUID主键

我这样做的原因是因为我将会话用作肮脏追踪器。我正在编写一个Windows窗体应用程序,我的每一个窗体都有一个单独的会话,该会话的持续时间与窗体的持续时间相同。会话尽可能保持断开连接,这样我就不会耗尽ADO.NET连接。它是一个MDI应用程序,可以打开的表单数量没有限制。每个表单还有一个OK按钮和一个Cancel按钮。OK按钮调用Session.Flush,然后关闭表单;“取消”按钮只是关闭表单,并自动放弃用户所做的所有更改


好吧,至少那是我想要的。上面的错误给我带来了问题。

除非你有很好的理由不这样做,否则你必须使用事务而不是显式刷新调用

using (var session = createSession())
{
   using (var transaction = session.BeginTransaction())
   {
      Cat x = new Cat();
      session.Save(x);
      x.Name = "fritz";
      try
      {
          transaction.Commit();
      }
      catch
      {
          // prevents your database from getting corrupt when you have a bug
          transaction.RollBack();
          throw;
      }
   }
}

在实际的应用程序中,最好将事务创建、提交和回滚隐藏在应用程序的单独部分中,这样就不必在每个数据访问块中调用它。在大多数使用关系数据库的应用程序中,一个事务被包装在为用户处理一个屏幕的整个代码中。这会导致用户所做的所有操作成功,或在出现错误时失败,作为一个原子块。用户在屏幕中更改的所有数据都会被存储,或者什么都不会存储,而不会存储其中的任何部分。

NHibernate确实会跟踪更改,但您编写的代码会导致它发出一个插入,其中包含您调用Save时的值,以及调用Save后所做更改的更新。Save使对象永久插入,然后NHibernate开始跟踪对永久对象更新所做的更改。刷新会话时,将提交插入和更新


我们的Windows窗体应用程序也面临类似的问题,我认为我们将采取不同的方法。FlushMode保留为自动默认模式,对象被逐出会话。如果用户取消操作,则从会话中逐出。逐出对象会使其成为瞬态,这正是所需的行为

是的,但我试着用一种不同的方式来使用NHibernate。我正在制作一个Windows应用程序,我正在使用会话进行更改跟踪。也就是说,当打开表单时,会启动会话。它保持断开连接,除非需要检索数据。表单有一个确定按钮和一个取消按钮。单击OK后,我调用Flush。如果单击“取消”,会话将以静默方式释放,所有更改都将丢失。它可以工作,除了这个问题…当然,我还将会话的FlushMode设置为Never,这样在用户单击OK之前就不会出现意外提交。演示模型!=域模型将flushmode设置为“从不”时,不会跟踪任何更改。这是不正确的。FlushMode从未被弃用为支持手动,但它们具有相同的效果:只有当应用程序显式调用Session.flush时才会刷新会话。等等,这是否意味着您将对象插入数据库,然后在用户取消时删除它?不可能。这意味着,如果用户取消操作,那么对象将从会话中退出,这样在刷新会话时不会保留任何更改。通常,这也标志着会话的结束。如果需要,将再次检索该对象以显示其以前的状态。哦,好的。但是如果NHibernate决定刷新您的会话,然后用户取消,会发生什么呢?事实上,你的疗程有多长?而且-您也有一个MDI应用程序,对吗?