The Dispose point is that it always starts. And, using this transaction commit icon, you do not need to know the difference.
using (var unitOfWork = new UnitOfWork()) {
Here we see that either an exception is thrown or unitOfWork is executed. Then we can have a bool in UnitOfWork to keep track of whether Commit was completed or not. Dispose can then not roll back. Thus, the unit of work is always either canceled or completed.
I would in any case avoid having Commit inside Dispose. To begin with, the ITransaction.Commit method ITransaction.Commit usually throw exceptions on errors - this is completely normal. However, the Dispose method should not throw exceptions. See this link and search Stackoverflow for more details on the reasons.
I think something like this with big bangs
class UnitOfWork : IDisposable { ISession _session; ITransation _transaction; bool _commitTried; // stuff goes here void Commit() { _commitTried = true; _transaction.Commit(); } void Dispose() { if (!_commitTried) _transaction.Rollback(); _transaction.Dispose(); _session.Dispose(); } }
The problem with forgetting to call Commit in general, I would say, is not so great, because if it is not perfect, the client code will not work, since the Rollback 'ed transaction and changes are not applied, which will be detected when the code is implemented inside the lamp or manually .
I really tried to handle this in one project using lambdas syntax like this
_repository.InTransactionDo(ThisMethodIsRunInsideATransaction);
Thus, customers did not have to worry about committing. I really ended up regretting it because he complicated the situation too much and wanted me to go with the above approach.
vidstige
source share