NHibernate - Cascade Merge到子实体对于分离的父实体失败

时间:2012-12-07 16:27:41

标签: c# asp.net nhibernate nhibernate-mapping spring.net

当前方法

在ASP.NET Web表单应用程序(使用Spring.NET和NHibernate)中,我们有一个聚合根( Person ),其详细信息可以在多个屏幕/页面中捕获。 Person 实体在进入此工作流之前存在,并且对 Person 对象图所做的所有更改都是原子的,因此只应在提交最终结果时刷新到数据库屏幕。

为实现这一目标,我们首次使用NHibernate 3.2从数据库加载 Person (懒惰)进入第一页,然后我们加载并保存序列化的 Person 当我们浏览整个过程时,将对象图形转换为HTTP会话变量。

从HTTP会话中检索 Person 后,它与当前的NHibernate会话处于分离状态,因此我们通过调用 Update()重新附加当前会话的方法,如下:

var sessionPerson = Session[PersonSessionName] as Person;
var currentSession = SessionFactory.GetCurrentSession();
currentSession.Update(sessionPerson);

注意:使用 Lock()引发异常,建议“重新关联的对象有脏集”。

重新连接时,我们可以按预期遍历对象图,从数据库中提取尚未加载到内存中的子实体的数据。

映射文件的子集

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="false" assembly="Domain" namespace=" TestApp.Domain">
  <class name="Person" table="Person">
    <id name="Id">
      <generator class="TestApp.CustomNHibernateHiLoGenerator, TestApp.Core" />
    </id>
    <property name="Name" not-null="false" />

    <bag name="PersonCountries" access="field.camelcase-underscore" cascade="all-delete-orphan">
      <key column="PersonId" foreign-key="FK_ PersonCountry_Person" not-null="true" />
      <one-to-many class="PersonCountry" />
    </bag>
  </class>

  <class name="Country" table="Country">
    <id name="Id">
      <generator class="TestApp.CustomNHibernateHiLoGenerator, TestApp.Core" />
    </id>
    ... No back reference to Person
  </class>
</hibernate-mapping>

public class PersonCountry : Entity, ICloneable
{
    // No properties of note
}

public class Person : Entity, ICloneable
{
    public virtual string Name { get; set; }
    public virtual IEnumerable<PersonCountry> PersonCountries { get; set; }
    ... 
    // More Properties
}

刷新对数据库的更改

.. // Code-behind
PricingService.Save(ProductContext.Pricing, forceMerge: true);            


public class PricingService : IPricingService
{
   [Transaction]  // Spring.NET transaction
   public Pricing Save(Pricing pricing, bool forceMerge = false)
   {            
      if(forceMerge)
      {
         CurrentSession.Merge(entity);
      }
      else
      {
         CurrentSession.SaveOrUpdate(entity);
      }
   }
}

当需要刷新对数据库的所有更改时,如果我们只更改名称,则更改将按预期工作。但是,向 Person 添加新的 Country 项会导致一对多关系中 Merge()的级联失败,并显示以下内容异常(奇怪的是,删除国家工作正常)。

NHibernate.StaleStateException: Batch update returned unexpected row count from update; actual row count: 0; Expected: 1

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:6)

每个具有有效Id的实体都被视为持久性,这就是为什么它尝试在合并中更新它但是因为它尚未保存但它失败了。在session.Flush()

之后致电session.Update()