为什么从Session中删除对象不会提交对数据库的更改?

时间:2012-02-16 05:04:24

标签: nhibernate

我在我的应用程序中使用NHibernate并具有以下情况。 (请注意,为了便于理解,这里的情况要简化得多)

从数据库中查询对象。它使用Session.Update()进行编辑和更新。然后在提交事务之前从会话中逐出该对象(使用Session.Evict(obj))。预期的结果是更改将持久保存到数据库中。

当我将Id列作为NHibernate identity列时,以前工作正常。 最近,我们将Id列更改为非身份。因此,除非我在Evict之前明确调用Session.Flush(),否则上述方案不会持久存储到数据库中。

有人能指出/向我解释这种行为的原因吗?

这个链接,NHibernate Session.Flush & Evict vs Clear,提及有关Evict和标识栏的内容,对我来说不太清楚。

2 个答案:

答案 0 :(得分:9)

您的工作流程不正确。

首先,当您从数据库中检索对象时,session.Update(entity)不会执行任何操作。更改将自动在Flush/Commit

上进行

接下来,Evict删除会话对该对象的所有知识,因此它不会保留对其应用的任何更改。在正常情况下,您几乎不应该使用此方法,这使我认为您没有正确处理会话。

第三,使用identity导致插入Save上立即发生的事实是一种限制,而非功能。

正确的工作流程是:

using (var session = factory.OpenSession())
using (var transaction = session.BeginTransaction())
{
    var entity = session.Get<EntityType>(id);
    entity.SomeProperty = newValue;
    transaction.Commit();
}

完全结构(using语句等)可以在桌面应用程序中更改,但基本思路是相同的。

答案 1 :(得分:2)

标识强制NHibernate立即将实体保存到数据库session.Save()非标识允许它批量插入以将它们作为整体发送。 Evict将从会话中删除对象的所有信息。因此,即使会话不知道,它在身份上也会忘记它已经在数据库中的实体。

补救你可以

  • 设置Flushmode.Auto(强制立即冲洗)
  • session.Flush()
  • 之前致电Evict
  • 交易完成后退出

哪个是最佳选择取决于上下文