I have a web application I’ve developed that has a fairly complex save routine. The user builds and modifies a series of plans and then chooses to save the data. All of the additions, deletions, and modifications are saved in one go at this point (all inside a single transaction).
Plan
Collection Of Child
Collection of ChildDetail
The bulk of the save is performed by calling SaveOrUpdate on a plan object and letting this save manage the plan and it’s children. I use zero as the unsaved value when I want to insert a new record and use cascade=all-delete-orphan to ensure that if a child object or child detail object is removed on the client side the object is deleted.
I am receiving an exception however when the following happens: A user creates a plan with child objects and saves them. This will save fine.
Plan(id=0)
Child[0](id=0), Child[1](id=0), Child[2](id=0)
If the user then removes the child objects, and adds new child objects in their place and then attempts to save the changes.
Plan(id=123)
Child[0](id=0), Child[1](id=0), Child[2](id=0)
This throws a GenericAdoException unable to insert Child with an inner exception “SQL0803 Duplicate Key Value Specified”.
The behavior I’m looking for is for NHibernate to delete the previous Child objects then insert the new ones when SaveOrUpdate is called on the Plan. How can I achieve this while still letting the parent manage the relationships?
A solution I found for the time being is to pass the Ids of the removed children to the save routine. I then set the ids of the new children to the ids of the removed children. Effectively turning a remove/add into an update.