NHibernate Remove and Add to ChildCollection ParentClass

I have the following problem.

I have a parent class with a set of child objects.

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; } } 

Classes map to nhibernate for the database, where the tblChild.colName column has a unique index.

  // 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"> 

My problem: The following code throws an exception due to a unique index:

  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(); 

The reason for the exception is that NHibernate first inserts child4, and then removes child1. Why does NHibernate do this? Can someone explain and can help me solve this problem?

+4
source share
1 answer

The order of the SQL statements is predefined in NHibernate:

SQL statements are issued in the following order

  • all insert entities, in the same order, the corresponding objects were saved using ISession.Save ()

  • all entity updates

  • all removal collections

  • all collection item deletes, updates, and inserts

  • all collection inserts

  • all entity deletions, in the same order the corresponding objects were deleted using ISession.Delete ()

NHibernate thinks that the new instance of the child object is actually a new object. Therefore, he first inserts it, violating the database constraint. This means that you have two options:

1) Discard immediately after removal and before adding a child.

2) Change your design so that instead of Remove / Add you simply edit it. This seems more logical, because it looks like Child is an object that is identified by a name. It is not clear why you are actually adding and removing the same child:

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

or like this:

 parent.DoSomethingWithChild("Child1"); 

PS I assume that your Child.Equals implementation uses a name, and in your mapping you have <one-to-many class="Child" /> , and not <one-to-many class="Parent" /> . This is probably just a typo.

+2
source

Source: https://habr.com/ru/post/1369672/


All Articles