UnitOfWork Order of Execution

Posts   
 
    
jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 11-May-2005 00:58:41   

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...

Jeff...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 11-May-2005 09:43:50   

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 disappointed

Frans Bouma | Lead developer LLBLGen Pro
jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 11-May-2005 19:12:24   

Otis wrote:

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 disappointed

Ok, this matches up with what I found by adding entities for deletion directly.

In the absence of code that will determine the proper order of execution, I say let the user work it out; let him be responsible for putting things in the proper order. IOW, just execute in the order he added elements to the UOW. At least then it's possible to get things in the right order...simple_smile

Jeff...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 11-May-2005 21:07:53   

Ok, and what to do about entities added per entity and entities added in a collection (a customer and his orders). wink . The collection has to be done first of course.

I though see I can solve this internally as well. I'll see if I can reschedule the things around without making things worse for existing code simple_smile

Frans Bouma | Lead developer LLBLGen Pro