예제 #1
0
        /// <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());
        }
예제 #2
0
        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);
        }
예제 #3
0
        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)));
        }
예제 #4
0
        /// <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));
            }));
        }