4

我有以下问题。

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

 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 会这样做?有人解释一下,可以帮我解决这个问题吗?

4

1 回答 1

2

NHibernate中预定义了 SQL 语句的顺序:

SQL 语句按以下顺序发出

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

  • 所有实体更新

  • 所有集合删除

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

  • 所有集合插入

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

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

1) 移除后和添加子之前立即冲洗。

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

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

或像这样:

parent.DoSomethingWithChild("Child1");

PS 我假设您的 Child.Equals 实现使用 name 并且在您的映射中您有<one-to-many class="Child" />,而不是<one-to-many class="Parent" />. 这可能只是一个错字。

于 2011-08-30T23:00:02.520 回答