I have seen unit of work pattern implemented with something like a following code:
private HashSet<object> _newEntities = new HashSet<object>();
private HashSet<object> _updatedEntities = new HashSet<object>();
private HashSet<object> _deletedEntities = new HashSet<object>();
and then there are methods for adding entities to each of these HashSets.
On Commit UnitOfWork creates some Mapper instance for each entity and calls Insert, Update, Delete methods from some imaginary Mapper.
The problem for me with this approach is: the names of Insert, Update, Delete methods are hard-coded, so it seems such a UnitOfWork is capable only of doing simple CRUD operations. But what if I need the following usage:
UnitOfWork ouw = new UnitOfWork();
uow.Start();
ARepository arep = new ARepository();
BRepository brep = new BRepository();
arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere();
uow.Commit();
Now the three-HashSet approach fails because I then I could register A and B entities only for Insert, Update, Delete operations but I need those custom operations now.
So it seems that I cannot always stack the Repository operations and then perform them all with UnitOfWork.Commit();
How to solve this problem? The first idea is - I could store addresses of methods
arep.DoSomeNonSimpleUpdateHere();
brep.DoSomeNonSimpleDeleteHere();
in UoW instance and execute them on uow.Commit()
but then I have also to store all the method parameters. That sounds complicated.
The other idea is to make Repositories completely UoW-aware: In DoSomeNonSimpleUpdateHere
I can detect that there is a UoW running and so I do not perform DoSomeNonSimpleUpdateHere
but save the operation parameters and 'pending' status in some stack of the Repository instance (obviously I cannot save everything in UoW because UoW shouldn't depend on concrete Repository implementations). And then I register the involved Repository in the UoW instance. When UoW calls Commit
, it opens a transaction, and calls some thing like Flush() for each pending Repository. Now every method of Repository needs some stuff for UoW detection and operation postponing for later Commit()
.
So the short question is - what is the easiest way to register all the pending changes in multiple repositories in UoW and then Commit()
them all in a single transaction?