【问题标题】:NHibernate Delete And Add In ChildCollection Of ParentClassNHibernate 删除并添加到 ParentClass 的 ChildCollection
【发布时间】:2011-08-30 14:35:43
【问题描述】:

我有以下问题。

我有一个包含子对象集合的父类。

 public class Parent{

      int _id;
      IList<Child> _childs = new List<Child>();


      public IList<Child> Childs {get;}
 }

 public class Child{

      int _id;
      string _name;
      Parent _parent;

      protected Child(){}

      public Child(Parent parent, string name){
         _parent = parent;
         _name = name;
      }
 }

这些类使用 nhibernate 映射到 tblChild.colName 列具有唯一索引的数据库。

 // Parent
 <bag name="_childs" access="field" cascade="all-delete-orphan" inverse="true">
    <key column="ParentId" />
    <one-to-many class="Parent" />
 </bag>

// Child
<many-to-one name="_parent" column="ParentId" cascade="none" access="field">

我的问题: 以下代码因唯一索引引发异常:

 Parent parent = new Parent();
 Child child1 = new Child(parent, "Child1");
 Child child2 = new Child(parent, "Child2");
 Child child3 = new Child(parent, "Child3");

 parent.Childs.Add(child1);
 parent.Childs.Add(child2);
 parent.Childs.Add(child3);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

 Child child4 = new Child(parent, "Child1"); // Duplicate Name
 parent.Childs.Remove(child1);
 parent.Childs.Add(child4);

 parentDao.Save(parent);
 parentDao.FlushAndClear();

异常的原因是NHibernate先插入child4,然后再移除child1。为什么 NHibernate 会这样做? 有人解释一下,可以帮我解决这个问题吗?

【问题讨论】:

    标签: nhibernate parent-child unique-index


    【解决方案1】:

    在NHibernate中SQL语句的顺序是predefined

    SQL语句按以下顺序发出

    • 所有实体插入,对应对象的顺序相同 使用 ISession.Save()

    • 保存
    • 所有实体更新

    • 所有集合删除

    • 所有集合元素的删除、更新和插入

    • 所有集合插入

    • 所有实体删除,对应对象的顺序相同 使用 ISession.Delete() 删除了

    NHibernate 认为 child 的新实例实际上是一个新实体。所以它首先插入它,违反了您的数据库约束。这意味着您有两种选择:

    1) 删除后和添加子级之前立即刷新。

    2) 稍微更改您的设计,以便您只需编辑子项,而不是删除/添加。这似乎更合乎逻辑,因为看起来 Child 是一个由 Name 标识的实体。目前尚不清楚您为什么实际添加和删除同一个孩子:

    Child child = parent.GetChildByName("Child1");
    child.DoSomething();
    

    或者像这样:

    parent.DoSomethingWithChild("Child1");
    

    附:我假设您的 Child.Equals 实现使用名称,并且在您的映射中您有&lt;one-to-many class="Child" /&gt;,而不是&lt;one-to-many class="Parent" /&gt;。这可能只是一个错字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-05
      • 2021-07-08
      • 2021-04-08
      相关资源
      最近更新 更多