I am experiencing the same problem ...
I have an entity which has a collection that is mapped to a table which contains a unique constraint.
What I do not understand is, that according to Stuarts reply, collection deletions should occur before collection inserts?
When I dive into the NHibernate sourcecode, I find the CollectionUpdateAction
class, which contains this code in its Execute
method:
persister.DeleteRows(collection, id, session);
persister.UpdateRows(collection, id, session);
persister.InsertRows(collection, id, session);
Then, I would assume that deletes are executed before inserts, but apparently this is not the case.
Is the CollectionUpdateAction not used in this scenario? When is the CollectionUpdateAction used?
Answer:
I have worked around this like this:
- In my mapping, I've set the cascade option to 'delete-orphan' instead of 'all-delete-orphan'
All my database access goes via a repository; in the save method of my repository, I have this code for my entity:
public void Save( Order orderObj )
{
// Only starts a transaction when there is no transaction
// associated yet with the session
With.Transaction(session, delegate()
{
session.SaveOrUpdate (orderObj);
session.Flush();
foreach( OrderLine line in orderObj.Lines )
{
session.SaveOrUpdate (line);
}
};
}
So, I save the orderObj, and because the cascade is set to delete-orphan, objects that are to be deleted, will be deleted from the database.
After I call SaveOrUpdate
, I must make sure to flush the changes to the database.
Since the delete-orphan cascade setting makes sure that no OrderLines are inserted or updated, I have to loop over my collection, and call 'SaveOrUpdate' for each OrderLine.
This will make sure that new OrderLines will be inserted, and modified ones are updated.
No action will be performed for OrderLines that have not changed.
Although it is not the ideal solution (it's an ugly hack IMHO), it kind of works, and it is abstracted away behind the repository, so this is how I deal with this problem for now...