Transaction commit pattern
Closed this issue · 4 comments
First of all, thanks for putting this repo online. It's a great source of inspiration to me.
However, I have one specific question: is there a reason why you commit the transaction on disposal? The controller might have already returned an OK response to the client while the transaction might fail during disposal afterwards.
Shouldn't you simply commit the transaction within UnitOfWork.Commit()
?
The controller won't return until all dependencies registered as per web request are disposed of. So, if there's a failure, the client will get a 500. It might be useful to commit early in some cases (e.g. to know if a DB uniqueness key is violated) and so you might want to introduce something like Flush on UnitOfWork. But generally, flushing all changes at the end of the web request is the essence of the Unit of Work pattern, it simplifies the code and increases performance (due to fewer db roundtrips).
The controller won't return until all dependencies registered as per web request are disposed of. So, if there's a failure, the client will get a 500.
You are not calling UnitOfWork.Dispose()
explicitly in BaseController.Ok()
. This means that it will be called when the UnitOfWork object is garbage collected. A potential exception can't bubble up back to the controller in that case. I was able to reproduce this exact behavior.
Wow you are right! I assumed an exception in a scoped dependency will bubble up but apparently they don't. It's not garbage collector, though. It's ASP.NET's built-in DI container that manages scoped dependencies and disposes of them after each web request.
I've pushed an update to UnitOfWork. Could you check on your side that it's working as expected now?
Yep, that works fine. Thanks!