/// <summary> /// Commits the changes within the persistence context. /// </summary> /// <param name="transactionScope">The transaction scope.</param> /// <returns>IServiceResponse{Boolean}.</returns> protected override IServiceResponse <Unit> CommitTransaction(TransactionScope transactionScope) { if (Parent == null) { try { using (transactionScope) { return(CommitTransactionInternal() .Catch(errors => { // TODO: (DG) Support exceptions! // If NContext exception vs error handling IS Exception-based, don't rollback here; just throw; Rollback(); // throw new NContextPersistenceException(errors); }) .Let(_ => { transactionScope.Complete(); })); } } catch (Exception exception) { Rollback(); // TODO: (DG) NContext Exception vs ErrorHandling return(ErrorBaseExtensions.ToServiceResponse(NContextPersistenceError.CommitFailed(Id, "tranId", new AggregateException(exception)))); } } return(CommitTransactionInternal()); }
private IUnitOfWork GetRequiredUnitOfWork(PersistenceOptions persistenceOptions) { if (!AmbientContextManager.AmbientExists) { return(GetRequiredNewUnitOfWork(persistenceOptions)); } if (!AmbientContextManager.Ambient.IsTypeOf <CompositeUnitOfWork>()) { throw NContextPersistenceError.CompositeUnitOfWorkWithinDifferentAmbientType(AmbientContextManager.Ambient.UnitOfWork.GetType()) .ToException <InvalidOperationException>(); } // TODO: (DG) If ambient is a Composite do we retain or add to it? //if () //{ // var currentCompositeUnitOfWork = (CompositeUnitOfWork)AmbientContextManager.Ambient.UnitOfWork; // unitOfWork = new CompositeUnitOfWork(AmbientContextManager, currentCompositeUnitOfWork, _PersistenceOptions); // currentCompositeUnitOfWork.AddUnitOfWork(unitOfWork); // AmbientContextManager.AddUnitOfWork(unitOfWork); //} AmbientContextManager.RetainAmbient(); return(AmbientContextManager.Ambient.UnitOfWork); }
private IServiceResponse <Unit> CommitChildrenParallel() { if (!AmbientContextManager.IsThreadSafe) { return(NContextPersistenceError.ConcurrencyUnsupported(AmbientContextManager.GetType()).ToServiceResponse()); } var commitExceptions = new ConcurrentQueue <Error>(); Parallel.ForEach( UnitsOfWork, new ParallelOptions { MaxDegreeOfParallelism = _PersistenceOptions.MaxDegreeOfParallelism }, (unitOfWork, state) => { try { if (state.IsExceptional || state.ShouldExitCurrentIteration) { return; } unitOfWork.Commit() .Catch(error => { state.Break(); commitExceptions.Enqueue(error); }); } catch (Exception exception) { state.Break(); commitExceptions.Enqueue(exception.ToError()); // TODO: (DG) Logging ... } }); return(commitExceptions.Any() ? (IServiceResponse <Unit>) new ErrorResponse <Unit>(new AggregateError((Int32)HttpStatusCode.InternalServerError, GetType().Name, commitExceptions.Select(error => error))) : (IServiceResponse <Unit>) new DataResponse <Unit>(default(Unit))); }
/// <summary> /// Commits the changes to the database. /// </summary> /// <returns>IServiceResponse{Boolean}.</returns> /// <exception cref="System.InvalidOperationException"></exception> public IServiceResponse <Unit> Commit() { if (Status == TransactionStatus.Active) { throw new InvalidOperationException(String.Format(LocalizedPersistenceError.UnitOfWorkCommitting, Id)); } if (Status == TransactionStatus.Committed) { throw new InvalidOperationException(String.Format(LocalizedPersistenceError.UnitOfWorkCommitted, Id)); } if (!AmbientContextManager.CanCommitUnitOfWork(this)) { return(NContextPersistenceError.UnitOfWorkNonCommittable(Id).ToServiceResponse()); } if (ScopeTransaction == null) { return(NContextPersistenceError.ScopeTransactionIsNull().ToServiceResponse()); } TransactionScope transactionScope = null; if (Parent == null && ScopeThread == Thread.CurrentThread) { // Use the existing CurrentTransaction. _CurrentTransactionFactory = new Lazy <Transaction>(() => ScopeTransaction); transactionScope = new TransactionScope(CurrentTransaction, TransactionOptions.Timeout); } else if (ScopeThread != Thread.CurrentThread) { // UnitOfWork is being committed on a different thread. _CurrentTransactionFactory = new Lazy <Transaction>(() => ScopeTransaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete)); transactionScope = new TransactionScope(CurrentTransaction, TransactionOptions.Timeout); } _Status = TransactionStatus.Active; return(CommitTransaction(transactionScope) .Catch(_ => { _Status = TransactionStatus.Aborted; }) .Bind(_ => { _Status = TransactionStatus.Committed; if (CurrentTransaction is DependentTransaction) { if (transactionScope != null) { transactionScope.Complete(); transactionScope.Dispose(); } var dependentTransaction = CurrentTransaction as DependentTransaction; dependentTransaction.Complete(); dependentTransaction.Dispose(); } else if (CurrentTransaction is CommittableTransaction) { try { (CurrentTransaction as CommittableTransaction).Commit(); } catch (TransactionAbortedException abortedException) { return NContextPersistenceError.CommitFailed(Id, CurrentTransaction.TransactionInformation.LocalIdentifier, abortedException) .ToServiceResponse(); } } return new DataResponse <Unit>(default(Unit)); })); }