About Unit Of Work Pattern :
Unit of Work design pattern does two important things: first it maintains in-memory updates and second it sends these in-memory updates as one transaction to the database
Assume that I need to use a web service and update a DB table in same unit of work. Conventionally, I perform these steps:
Insert
method (there is no risk if it is performed, but it is not FLUSHED at that moment in UOW ).If web service results is 200 (OK) then call commit, else rollback.
using (var unitOfWork = _unitOfWorkManager.Begin())
{
_personRepository.Insert(person);
externalWebService.IncrementPeopleCount();
unitOfWork.Complete();
}
unitOfWork
has one method: Complete()
.If web service gets error, it's not problem.Because I can throw exception, so complete() method doesn't execute. But I get error in complete() I must reverse web service?
It would work fine if Insert() method transactional is performed in DB (not commit yet).
How can I do this scenario in Unit of Work pattern? Or is it absolutely necessary to have a reverse web method DecrementPeopleCount
?
In Unit of Work
you manage transactional
operations. In Unit of Work
scope, you run some business logic and when all operation is ready, Complete
or SaveChanges
operations is called. This operations gives you a chance, all your operation finish successfully or all of your operations canceled. In this case, code does not works as a unit. There are two separete operations, insert operations and web service increment operations.
DecrementPeopleCount
operations is not a solution. Imagine something like that: IncrementPeopleCount operation return successfull, however Complete operation return error. After this point you try to call DecrementPeopleCount but webservice is too busy or network problems occur. In this way, still your code does not works as a unit.
As a solution, you consider change your approach.
1) WebService call operation can be wrap and converted as transactional operation. I suggest a tool which is name Hangfire
. It save operations name and parameters in db and transaction complete it read db and trigger registerd functions. You can save entity
and call webservice operation execution
in db as one operations.
2) You can save entity
and publish user-created event
or increment-user-count command
. Your observer/consumer consumed that event/command and execute web api call.
Both of solutions gives eventually consistancy.