11
votes

I'm trying to figure out why NHibernate handles one-to-many cascading (using cascade=all-delete-orphan) the way it does. I ran into the same issue as this guy:

Forcing NHibernate to cascade delete before inserts

As far as I can tell NHibernate always performs inserts first, then updates, then deletes. There may be a very good reason for this, but I can't for the life of me figure out what that reason is. I'm hoping that a better understanding of this will help me come up with a solution that I don't hate :)

Are there any good theories on this behavior? In what scenario would deleting orphans first not work? Do all ORMs work this way?

1
Just want to add my frustration to this question. NHibernate is an absolute failure in this case. I've been fighting all day with this stupid issue. Even the most basic ORMs handle this much much more gracefully then NHibernate. I ended up having to completely code around this. You and I both must have missed something.JasonCoder

1 Answers

3
votes

EDIT: After saying there is no reason, here is a reason. Lets say you have the following scenario:

public class Dog {
  public DogLeg StrongestLeg {get;set;}
  public IList<DogLeg> Legs {get;set;
}

If you were to delete first, and lets say you delete all of Dog.Legs, then you may delete the StrongestLeg which would cause a reference violation. Hence you cannot DELETE before you UPDATE.

Lets say you add a new leg, and that new leg is also the StrongestLeg. Then you must INSERT before you UPDATE so that the Leg has an Id that can be inserted into Dog.StrongestLegId.

So you must INSERT, UPDATE, then DELETE.

Also as nHibernate is based on Hibernate, I had a look into Hibernate and found several people talking about the same issue.

And here is the best answer from them:

Gail Badner added a comment - 21/Feb/08 2:30 PM: The problem arises when a new association entity with a generated ID is added to the collection. The first step, when merging an entity containing this collection, is to cascade save the new association entity. The cascade must occur before other changes to the collection. Because the unique key for this new association entity is the same as an entity that is already persisted, a ConstraintViolationException is thrown. This is expected behavior.