public void Unwraps_Nested_exceptions()
            {
                var innerException = new TimeoutException("", new EntityException("", new DbUpdateException("", new UpdateException(""))));

                Assert.True(
                    DbExecutionStrategy.UnwrapAndHandleException(
                        new EntityException("", new DbUpdateException("", new UpdateException("", innerException))),
                        ex =>
                {
                    Assert.Same(innerException, ex);
                    return(true);
                }));
            }
            public void Unwraps_wrapped_null_exception()
            {
                Exception innerException = null;

                Assert.True(
                    DbExecutionStrategy.UnwrapAndHandleException(
                        new UpdateException("", innerException),
                        ex =>
                {
                    Assert.Same(innerException, ex);
                    return(true);
                }));
            }
            public void Unwraps_UpdateException()
            {
                var innerException = new TimeoutException();

                Assert.True(
                    DbExecutionStrategy.UnwrapAndHandleException(
                        new UpdateException("", innerException),
                        ex =>
                {
                    Assert.Same(innerException, ex);
                    return(true);
                }));
            }
예제 #4
0
        private async Task <TResult> ProtectedExecuteAsync <TResult>(
            Func <Task <TResult> > operation,
            CancellationToken cancellationToken)
        {
            TimeSpan?delay;
            TResult  result;

            while (true)
            {
                try
                {
                    result = await operation().WithCurrentCulture <TResult>();

                    goto label_10;
                }
                catch (Exception ex)
                {
                    if (!DbExecutionStrategy.UnwrapAndHandleException <bool>(ex, new Func <Exception, bool>(this.ShouldRetryOn)))
                    {
                        throw;
                    }
                    else
                    {
                        delay = this.GetNextDelay(ex);
                        if (!delay.HasValue)
                        {
                            throw new RetryLimitExceededException(Strings.ExecutionStrategy_RetryLimitExceeded((object)this._maxRetryCount, (object)this.GetType().Name), ex);
                        }
                    }
                }
                TimeSpan?nullable = delay;
                TimeSpan zero     = TimeSpan.Zero;
                if ((nullable.HasValue ? (nullable.GetValueOrDefault() < zero ? 1 : 0) : 0) == 0)
                {
                    await Task.Delay(delay.Value, cancellationToken).WithCurrentCulture();
                }
                else
                {
                    break;
                }
            }
            throw new InvalidOperationException(Strings.ExecutionStrategy_NegativeDelay((object)delay));
label_10:
            return(result);
        }
예제 #5
0
        /// <summary>
        /// Repetitively executes the specified operation while it satisfies the current retry policy.
        /// </summary>
        /// <typeparam name="TResult">The type of result expected from the executable operation.</typeparam>
        /// <param name="operation">
        /// A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
        /// </param>
        /// <returns>The result from the operation.</returns>
        /// <exception cref="T:System.Data.Entity.Infrastructure.RetryLimitExceededException">if the retry delay strategy determines the operation shouldn't be retried anymore</exception>
        /// <exception cref="T:System.InvalidOperationException">if an existing transaction is detected and the execution strategy doesn't support it</exception>
        /// <exception cref="T:System.InvalidOperationException">if this instance was already used to execute an operation</exception>
        public TResult Execute <TResult>(Func <TResult> operation)
        {
            Check.NotNull <Func <TResult> >(operation, nameof(operation));
            this.EnsurePreexecutionState();
            TimeSpan?nextDelay;

            while (true)
            {
                try
                {
                    return(operation());
                }
                catch (Exception ex)
                {
                    if (!DbExecutionStrategy.UnwrapAndHandleException <bool>(ex, new Func <Exception, bool>(this.ShouldRetryOn)))
                    {
                        throw;
                    }
                    else
                    {
                        nextDelay = this.GetNextDelay(ex);
                        if (!nextDelay.HasValue)
                        {
                            throw new RetryLimitExceededException(Strings.ExecutionStrategy_RetryLimitExceeded((object)this._maxRetryCount, (object)this.GetType().Name), ex);
                        }
                    }
                }
                TimeSpan?nullable = nextDelay;
                TimeSpan zero     = TimeSpan.Zero;
                if ((nullable.HasValue ? (nullable.GetValueOrDefault() < zero ? 1 : 0) : 0) == 0)
                {
                    Thread.Sleep(nextDelay.Value);
                }
                else
                {
                    break;
                }
            }
            throw new InvalidOperationException(Strings.ExecutionStrategy_NegativeDelay((object)nextDelay));
        }
예제 #6
0
        /// <summary>
        /// Recursively gets InnerException from <paramref name="exception" /> as long as it's an
        /// <see cref="T:System.Data.Entity.Core.EntityException" />, <see cref="T:System.Data.Entity.Infrastructure.DbUpdateException" /> or <see cref="T:System.Data.Entity.Core.UpdateException" />
        /// and passes it to <paramref name="exceptionHandler" />
        /// </summary>
        /// <typeparam name="T">The type of the unwrapped exception.</typeparam>
        /// <param name="exception"> The exception to be unwrapped. </param>
        /// <param name="exceptionHandler"> A delegate that will be called with the unwrapped exception. </param>
        /// <returns>
        /// The result from <paramref name="exceptionHandler" />.
        /// </returns>
        public static T UnwrapAndHandleException <T>(
            Exception exception,
            Func <Exception, T> exceptionHandler)
        {
            EntityException entityException = exception as EntityException;

            if (entityException != null)
            {
                return(DbExecutionStrategy.UnwrapAndHandleException <T>(entityException.InnerException, exceptionHandler));
            }
            DbUpdateException dbUpdateException = exception as DbUpdateException;

            if (dbUpdateException != null)
            {
                return(DbExecutionStrategy.UnwrapAndHandleException <T>(dbUpdateException.InnerException, exceptionHandler));
            }
            UpdateException updateException = exception as UpdateException;

            if (updateException != null)
            {
                return(DbExecutionStrategy.UnwrapAndHandleException <T>(updateException.InnerException, exceptionHandler));
            }
            return(exceptionHandler(exception));
        }