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); })); }
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); }
/// <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)); }
/// <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)); }