NHibernate Удалить и добавить в ChildCollection ParentClass

У меня следующая проблема.

У меня есть родительский класс с коллекцией дочерних объектов.

 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 сначала вставляет дочерний элемент4, а затем удаляет дочерний элемент1. Почему NHibernate делает это? Кто-то объяснение и может помочь мне решить эту проблему?


person Tobias    schedule 30.08.2011    source источник


Ответы (1)


Порядок операторов SQL предопределен в NHibernate:

Операторы SQL выполняются в следующем порядке

  • все сущности вставки, в том же порядке соответствующие объекты были сохранены с помощью ISession.Save()

  • все обновления сущностей

  • вся коллекция удаления

  • все удаления, обновления и вставки элементов коллекции

  • все вставки коллекции

  • все удаления объектов, в том же порядке соответствующие объекты были удалены с помощью ISession.Delete()

NHibernate считает, что новый экземпляр дочернего элемента на самом деле является новой сущностью. Поэтому он вставляет его первым, нарушая ограничение вашей базы данных. Это означает, что у вас есть два варианта:

1) Промыть сразу после удаления и перед добавлением ребенка.

2) Немного измените свой дизайн, чтобы вместо Удалить/Добавить вы просто редактировали дочерний элемент. Это кажется более логичным, потому что похоже, что Child — это сущность, которая идентифицируется по имени. Непонятно, почему вы на самом деле добавляете и удаляете одного и того же ребенка:

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

или вот так:

parent.DoSomethingWithChild("Child1");

P.S. Я предполагаю, что ваша реализация Child.Equals использует имя, а в вашем сопоставлении у вас есть <one-to-many class="Child" />, а не <one-to-many class="Parent" />. Вероятно, это просто опечатка.

person Dmitry    schedule 30.08.2011