/// <summary> /// This method can run synchronous as well as asynchronous operations within a transaction /// in the order in which the operations are written in the consumer class.Here synchronous /// as well as asynchronous operations are hadnled since "Task" also inherently handles both /// synchronous and asynchronous scenarios. /// /// </summary> /// <param name="shouldCommitSynchronousOperationsFirst"></param> /// <param name="shouldAutomaticallyRollBackOnTransactionException"></param> /// <param name="shouldThrowOnException"></param> /// <returns></returns> public async Task CommitAsync(CancellationToken token = default(CancellationToken), bool shouldAutomaticallyRollBackOnTransactionException = true, bool shouldThrowOnException = true) { CheckForObjectAlreadyDisposedOrNot(typeof(UnitOfWork).FullName); ContractUtility.Requires <ArgumentOutOfRangeException>(_operationsQueue.Count > 0, "Atleast one operation must be there to be executed."); ContractUtility.Requires <NotSupportedException>(_operationsQueue.Any(x => x.AsyncOperation.IsNotNull()), "If CommitAsync method is used,there needs to be atleast one async operation exceuted." + "Please use Commit method(instead of CommitAsync) if there is not " + "a single async operation."); await ExceptionHandlingUtility.HandleExceptionWithNullCheck(async x => { _scope = TransactionUtility.GetTransactionScope(_isoLevel, _scopeOption, true); try { while (_operationsQueue.Count > 0) { #if TEST ThrowExceptionForRollbackCheck(); #endif OperationData operationData = _operationsQueue.Dequeue(); if (operationData.Operation.IsNotNull()) { operationData.Operation(); } else if (operationData.AsyncOperation.IsNotNull()) { await operationData.AsyncOperation(x); } } CompleteScope(() => { _scope.Complete(); // this just completes the transaction.Not yet committed here. _scope.Dispose(); // After everthing runs successfully within the transaction // and after completion, this should be called to actually commit the data // within the transaction scope. }, shouldAutomaticallyRollBackOnTransactionException, shouldThrowOnException); } catch (Exception ex) { //Although ex is not exactly a commit exception but still passing it to reuse Rollback method.Using the Rollback //method to reuse exception handling and dispose the transaction scope object(else it can cause issues for the //future transactions). Rollback(ex); } }, token, _exceptionHandler, null);//TODO - proper exception handling compensating handler needs to be here }
/// <summary> /// Comits all the data within this unit of work instance in an atomic way i.e. all or none get transacted. /// Order of operations of different instances of same type or different types needs to be handled at /// the Business or Service Layer. /// </summary> /// <param name="shouldAutomaticallyRollBackOnTransactionException">when set to true(default value) /// the RollBack method need not be called from the consumer class</param> public void Commit(bool shouldAutomaticallyRollBackOnTransactionException = true, bool shouldThrowOnException = true) { ContractUtility.Requires <ArgumentOutOfRangeException>(_operationsQueue.IsNotNullOrEmpty(), "Atleast one operation must be there to be executed."); ContractUtility.Requires <NotSupportedException>(_operationsQueue.All(x => x.AsyncOperation.IsNull()), "Async operations are not supported by Commit method.Use CommitAsync instead."); ExceptionHandlingUtility.HandleExceptionWithNullCheck(() => { _scope = TransactionUtility.GetTransactionScope(_isoLevel, _scopeOption); try { while (_operationsQueue.Count > 0) { #if TEST ThrowExceptionForRollbackCheck(); #endif OperationData operationData = _operationsQueue.Dequeue(); if (operationData.Operation.IsNotNull()) { operationData.Operation(); } } CompleteScope(() => { _scope.Complete(); // this just completes the transaction.Not yet committed here. _scope.Dispose(); // After everthing runs successfully within the transaction // and after completion, this should be called to actually commit the data // within the transaction scope. }, shouldAutomaticallyRollBackOnTransactionException, shouldThrowOnException); } catch (Exception ex) { //Although ex is not exactly a commit exception but still passing it to reuse Rollback method.Using the Rollback //method to reuse exception handling and dispose the transaction scope object(else it can cause issues for the //future transactions). Rollback(ex); } }, _exceptionHandler);//TODO - proper exception handling compensating handler needs to be here }