public T Run <T>(Func <T> workflow)
        {
            T result = default;

            ExecutionStrategyExtensions.Execute(
                _context.Database.CreateExecutionStrategy(),
                () =>
            {
                try
                {
                    using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
                    result          = workflow();
                    scope.Complete();
                }
                catch (TransactionAbortedException e)
                {
                    _logger.LogError(e, "Commit error");
                    throw;
                }
                catch (AggregateException ae)
                {
                    throw ae.Flatten();
                }
            }
                );
            return(result);
        }
Ejemplo n.º 2
0
 /// <summary>
 ///     Executes the specified operation in a transaction and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="state"> The state that will be passed to the operation. </param>
 /// <param name="operation">
 ///     A delegate representing an executable operation that returns the result of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <param name="isolationLevel"> The isolation level to use for the transaction. </param>
 /// <typeparam name="TState"> The type of the state. </typeparam>
 /// <typeparam name="TResult"> The return type of <paramref name="operation" />. </typeparam>
 /// <returns> The result from the operation. </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static TResult ExecuteInTransaction <TState, TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [CanBeNull] TState state,
     [NotNull] Func <TState, TResult> operation,
     [NotNull] Func <TState, bool> verifySucceeded,
     IsolationLevel isolationLevel)
 => ExecutionStrategyExtensions.ExecuteInTransaction(
     strategy, state, operation, verifySucceeded, c => c.Database.BeginTransaction(isolationLevel));
Ejemplo n.º 3
0
 /// <summary>
 ///     Executes the specified asynchronous operation and returns the result. Allows to check whether
 ///     the transaction has been rolled back if an error occurs during commit.
 /// </summary>
 /// <param name="strategy"> The strategy that will be used for the execution. </param>
 /// <param name="state"> The state that will be passed to the operation. </param>
 /// <param name="operation">
 ///     A function that returns a started task of type <typeparamref name="TResult" />.
 /// </param>
 /// <param name="verifySucceeded">
 ///     A delegate that tests whether the operation succeeded even though an exception was thrown when the
 ///     transaction was being committed.
 /// </param>
 /// <param name="isolationLevel"> The isolation level to use for the transaction. </param>
 /// <param name="cancellationToken">
 ///     A cancellation token used to cancel the retry operation, but not operations that are already in flight
 ///     or that already completed successfully.
 /// </param>
 /// <typeparam name="TState"> The type of the state. </typeparam>
 /// <typeparam name="TResult"> The result type of the <see cref="Task{TResult}" /> returned by <paramref name="operation" />. </typeparam>
 /// <returns>
 ///     A task that will run to completion if the original task completes successfully (either the
 ///     first time or after retrying transient failures). If the task fails with a non-transient error or
 ///     the retry limit is reached, the returned task will become faulted and the exception must be observed.
 /// </returns>
 /// <exception cref="RetryLimitExceededException">
 ///     The operation has not succeeded after the configured number of retries.
 /// </exception>
 public static Task <TResult> ExecuteInTransactionAsync <TState, TResult>(
     [NotNull] this IExecutionStrategy strategy,
     [CanBeNull] TState state,
     [NotNull] Func <TState, CancellationToken, Task <TResult> > operation,
     [NotNull] Func <TState, CancellationToken, Task <bool> > verifySucceeded,
     IsolationLevel isolationLevel,
     CancellationToken cancellationToken = default(CancellationToken))
 => ExecutionStrategyExtensions.ExecuteInTransactionAsync(
     strategy, state, operation, verifySucceeded, (c, ct) => c.Database.BeginTransactionAsync(isolationLevel, ct), cancellationToken);