jeffreygg wrote:
Hi, Frans.
Ran into a bit of problem with the UnitOfWork class. It seems that when adding collections for deletion that the order the collections are added to the UnitOfWork is not the order in which contained entities are deleted.
The data: Activities 1:n Tasks
semi-pseudocode
uow.AddCollectionForDelete(tasks)
uow.AddCollectionForDelete(activities)
uow.Commit
A foreign key constraint exception gets thrown for task.ActivityID. Looking in profiler confirms that the first item being deleted is an Activity, when it should be a Task.
Looking in the source code at UnitOfWork.Commit (line 541), it appears that each entity in the collection is added to the commit queue by using the AddForDelete overload:
AddForDelete(IEntity2 entityToDelete, IPredicateExpression restriction, bool append)
but "False" is being passed in for append which results in the entities being queued for deletion in reverse order. Or so it appears...
Can you confirm this for me? I'm going to manually add the entities to the UOW and see if that clears it up for me...
They're inserted at the front of the queue. This is done because in the vast majority of cases, when you want to delete a hierarchy, the root entity has to be deleted last, the child entities have to be deleted first, and IF they're in a collection, they're on the FK side, so should be deleted first.
This is a quick hack, as the bug was reported very close to release and I didn't have any time to implement a full graph traversal routine to put them all in the right order, and that even wouldn't prevent FK violations, for example if not all FK entities were loaded into the UoW or in the graph. So I decided this would be as sufficient as a full graph traversal.
The collections are processed in the order they were added to the UoW. Per collection the entities are added in front of the queue, so in your case, add the FK side last, the PK side first.
It's a bit of a problem, I admit. The sad part is that errors with FK violations can't be avoided without loading all data into memory first