internal DbContextScope(
            Func <TDbContext> dbContextFactory,
            AmbientScopeOption scopeOption)
            : base(scopeOption)
        {
            // Activate, gaining access to the potential parent scope
            this.Activate();

            try
            {
                this.UnitOfWork = this.EffectiveParentScope?.UnitOfWork ?? new UnitOfWork <TDbContext>(dbContextFactory);
            }
            catch
            {
                // Dispose ourselves on failure, ensuring that we are deactivated
                this.Dispose();
                throw;
            }
        }
Пример #2
0
 public virtual TResult ExecuteInDbContextScope <TState, TResult>(
     AmbientScopeOption scopeOption,
     TState state, Func <IExecutionScope <TState>, TResult> task)
 {
     return(TransactionalStrategyExecutor.ExecuteInDbContextScope(this, scopeOption, state, task));
 }
Пример #3
0
 /// <summary>
 /// Constructs a new instance that defers to the given loggers.
 /// </summary>
 /// <param name="scopeOption">Allows joining any existing scope (i.e. adding additional logging mechanisms) or obscuring it (i.e. temporarily replacing the logging mechanisms).</param>
 /// <param name="loggers">The loggers to defer to.</param>
 public LogScope(AmbientScopeOption scopeOption, IEnumerable <ILogger> loggers)
     : this(scopeOption, loggers, isDefaultScope : false)
 {
 }
 private protected DbContextScope(AmbientScopeOption scopeOption)
     : base(scopeOption)
 {
 }
Пример #5
0
 /// <summary>
 /// Private constructor.
 /// Does not activate this instance.
 /// </summary>
 private IdGeneratorScope(IIdGenerator idGenerator, AmbientScopeOption ambientScopeOption)
     : base(ambientScopeOption)
 {
     this.IdGenerator = idGenerator ?? throw new ArgumentNullException(nameof(idGenerator));
 }
Пример #6
0
 public ManuallyActivatedScope(int index, AmbientScopeOption scopeOption, bool noNestingIgnoresDefaultScope = false)
     : base(scopeOption)
 {
     this.Index = index;
     this.NoNestingIgnoresDefaultScope = noNestingIgnoresDefaultScope;
 }
Пример #7
0
 public static TResult ExecuteInDbContextScope <TContext, TState, TResult>(IDbContextProvider <TContext> provider,
                                                                           AmbientScopeOption scopeOption,
                                                                           TState state, Func <IExecutionScope <TState>, TResult> task)
 {
     return(ExecuteInDbContextScopeAsync(provider, scopeOption, state, cancellationToken: default, ExecuteSynchronously, async: false, GetUnitOfWorkFromDbContextScope)
Пример #8
0
 /// <summary>
 /// <para>
 /// Performs the given <paramref name="task"/>, with access to a new ambient <typeparamref name="TDbContext"/> accessible through <see cref="IDbContextAccessor{TDbContext}"/>.
 /// </para>
 /// <para>
 /// This is the preferred way to perform work in the scope of a <see cref="DbContext"/>. It takes care of many concerns automatically.
 /// </para>
 /// <para>
 /// The task is performed through the <see cref="DbContext"/>'s <see cref="IExecutionStrategy"/>.
 /// The <see cref="IExecutionStrategy"/> may provide behavior such as retry attempts on transient exceptions.
 /// Each attempt is provided with a fresh <see cref="DbContext"/>, with no state leakage.
 /// </para>
 /// <para>
 /// If a query is executed that might perform a write operation, a transaction is started automatically.
 /// (This comes at no additional cost, since otherwise Entity Framework starts its own transaction when saving.)
 /// The transaction is committed once the scope ends, provided that it has not aborted.
 /// </para>
 /// <para>
 /// Scopes can be nested. When a scope joins an outer scope, its work is simply performed as part of the outer scope's work, with the outer scope taking care of all the above.
 /// </para>
 /// <para>
 /// A scope aborts when an exception bubbles up from its task or when <see cref="IExecutionScope.Abort"/> is called. At the end of an aborted scope, any ongoing transaction is rolled back.
 /// Further attempts to use that <see cref="DbContext"/>, even by joined parent scopes, result in a <see cref="TransactionAbortedException"/>.
 /// </para>
 /// </summary>
 public static Task <TResult> ExecuteInDbContextScopeAsync <TDbContext, TResult>(this IDbContextProvider <TDbContext> provider,
                                                                                 AmbientScopeOption scopeOption,
                                                                                 Func <IExecutionScope, Task <TResult> > task)
 {
     return(provider.ExecuteInDbContextScopeAsync(scopeOption, state: task, default, (scope, _) => scope.State(scope)));
 /// <summary>
 /// Private constructor.
 /// Does not activate this instance.
 /// </summary>
 private PublicIdentityScope(IPublicIdentityConverter converter, AmbientScopeOption ambientScopeOption)
     : base(ambientScopeOption)
 {
     this.Converter = converter ?? throw new ArgumentNullException(nameof(converter));
 }
 /// <summary>
 /// Private constructor.
 /// Does not activate.
 /// </summary>
 private TestDetector(bool isTestRun, AmbientScopeOption ambientScopeOption)
     : base(ambientScopeOption)
 {
     this._isTestRun = isTestRun;
 }
Пример #11
0
 public override Task <TResult> ExecuteInDbContextScopeAsync <TState, TResult>(AmbientScopeOption scopeOption, TState state, CancellationToken cancellationToken, Func <IExecutionScope <TState>, CancellationToken, Task <TResult> > task)
 {
     return(this.WrappedProvider.ExecuteInDbContextScopeAsync(scopeOption, state, cancellationToken, async(scope, ct) =>
     {
         var shouldThrow = this.ShouldThrow();
         var result = await task(scope, ct).ConfigureAwait(false);
         ThrowConcurrencyException(shouldThrow);
         return result;
     }));
 }
 /// <summary>
 /// <para>
 /// Performs the given <paramref name="task"/>, with access to a new ambient <typeparamref name="TDbContext"/> accessible through <see cref="IDbContextAccessor{TDbContext}"/>.
 /// </para>
 /// <para>
 /// This is the preferred way to perform work in the scope of a <see cref="DbContext"/>. It takes care of many concerns automatically.
 /// </para>
 /// <para>
 /// The task is performed through the <see cref="DbContext"/>'s <see cref="IExecutionStrategy"/>.
 /// The <see cref="IExecutionStrategy"/> may provide behavior such as retry attempts on transient exceptions.
 /// Each attempt is provided with a fresh <see cref="DbContext"/>, with no state leakage.
 /// </para>
 /// <para>
 /// If a query is executed that might perform a write operation, a transaction is started automatically.
 /// (This comes at no additional cost, since otherwise Entity Framework starts its own transaction when saving.)
 /// The transaction is committed once the scope ends, provided that it has not aborted.
 /// </para>
 /// <para>
 /// Scopes can be nested. When a scope joins an outer scope, its work is simply performed as part of the outer scope's work, with the outer scope taking care of all the above.
 /// </para>
 /// <para>
 /// A scope aborts when an exception bubbles up from its task or when <see cref="IExecutionScope.Abort"/> is called. At the end of an aborted scope, any ongoing transaction is rolled back.
 /// Further attempts to use that <see cref="DbContext"/>, even by joined parent scopes, result in a <see cref="TransactionAbortedException"/>.
 /// </para>
 /// </summary>
 public static void ExecuteInDbContextScope <TDbContext>(this IDbContextProvider <TDbContext> provider,
                                                         AmbientScopeOption scopeOption,
                                                         Action <IExecutionScope> task)
 {
     provider.ExecuteInDbContextScope(scopeOption, state: task, scope => scope.State(scope));
 }
 /// <summary>
 /// <para>
 /// Performs the given <paramref name="task"/>, with access to a new ambient <typeparamref name="TDbContext"/> accessible through <see cref="IDbContextAccessor{TDbContext}"/>.
 /// </para>
 /// <para>
 /// This is the preferred way to perform work in the scope of a <see cref="DbContext"/>. It takes care of many concerns automatically.
 /// </para>
 /// <para>
 /// The task is performed through the <see cref="DbContext"/>'s <see cref="IExecutionStrategy"/>.
 /// The <see cref="IExecutionStrategy"/> may provide behavior such as retry attempts on transient exceptions.
 /// Each attempt is provided with a fresh <see cref="DbContext"/>, with no state leakage.
 /// </para>
 /// <para>
 /// If a query is executed that might perform a write operation, a transaction is started automatically.
 /// (This comes at no additional cost, since otherwise Entity Framework starts its own transaction when saving.)
 /// The transaction is committed once the scope ends, provided that it has not aborted.
 /// </para>
 /// <para>
 /// Scopes can be nested. When a scope joins an outer scope, its work is simply performed as part of the outer scope's work, with the outer scope taking care of all the above.
 /// </para>
 /// <para>
 /// A scope aborts when an exception bubbles up from its task or when <see cref="IExecutionScope.Abort"/> is called. At the end of an aborted scope, any ongoing transaction is rolled back.
 /// Further attempts to use that <see cref="DbContext"/>, even by joined parent scopes, result in a <see cref="TransactionAbortedException"/>.
 /// </para>
 /// </summary>
 public static TResult ExecuteInDbContextScope <TDbContext, TResult>(this IDbContextProvider <TDbContext> provider,
                                                                     AmbientScopeOption scopeOption,
                                                                     Func <IExecutionScope, TResult> task)
 {
     return(provider.ExecuteInDbContextScope(scopeOption, state: task, scope => scope.State(scope)));
 }
Пример #14
0
 public virtual Task <TResult> ExecuteInDbContextScopeAsync <TState, TResult>(
     AmbientScopeOption scopeOption,
     TState state, CancellationToken cancellationToken, Func <IExecutionScope <TState>, CancellationToken, Task <TResult> > task)
 {
     return(TransactionalStrategyExecutor.ExecuteInDbContextScopeAsync(this, scopeOption, state, cancellationToken, task));
 }
 protected AsyncAmbientScope(AmbientScopeOption scopeOption)
     : base(scopeOption)
 {
 }
Пример #16
0
 /// <summary>
 /// <para>
 /// Performs the given <paramref name="task"/>, with access to a new ambient <typeparamref name="TDbContext"/> accessible through <see cref="IDbContextAccessor{TDbContext}"/>.
 /// </para>
 /// <para>
 /// This is the preferred way to perform work in the scope of a <see cref="DbContext"/>. It takes care of many concerns automatically.
 /// </para>
 /// <para>
 /// The task is performed through the <see cref="DbContext"/>'s <see cref="IExecutionStrategy"/>.
 /// The <see cref="IExecutionStrategy"/> may provide behavior such as retry attempts on transient exceptions.
 /// Each attempt is provided with a fresh <see cref="DbContext"/>, with no state leakage.
 /// </para>
 /// <para>
 /// If a query is executed that might perform a write operation, a transaction is started automatically.
 /// (This comes at no additional cost, since otherwise Entity Framework starts its own transaction when saving.)
 /// The transaction is committed once the scope ends, provided that it has not aborted.
 /// </para>
 /// <para>
 /// Scopes can be nested. When a scope joins an outer scope, its work is simply performed as part of the outer scope's work, with the outer scope taking care of all the above.
 /// </para>
 /// <para>
 /// A scope aborts when an exception bubbles up from its task or when <see cref="IExecutionScope.Abort"/> is called. At the end of an aborted scope, any ongoing transaction is rolled back.
 /// Further attempts to use that <see cref="DbContext"/>, even by joined parent scopes, result in a <see cref="TransactionAbortedException"/>.
 /// </para>
 /// </summary>
 public static Task ExecuteInDbContextScopeAsync <TDbContext>(this IDbContextProvider <TDbContext> provider,
                                                              AmbientScopeOption scopeOption,
                                                              CancellationToken cancellationToken, Func <IExecutionScope, CancellationToken, Task> task)
 {
     return(provider.ExecuteInDbContextScopeAsync(scopeOption, state: task, cancellationToken, (scope, ct) => scope.State(scope, ct)));
 }
Пример #17
0
 private DistributedIdGeneratorScope(IDistributedIdGenerator idGenerator, AmbientScopeOption scopeOption)
     : base(scopeOption)
 {
     this.IdGenerator = idGenerator ?? throw new ArgumentNullException(nameof(idGenerator));
 }
 /// <summary>
 /// Private constructor.
 /// Does not activate this instance.
 /// </summary>
 private ClockScope(Func <DateTime> nowSource, AmbientScopeOption ambientScopeOption)
     : base(ambientScopeOption)
 {
     this.NowSource = nowSource ?? throw new ArgumentNullException(nameof(nowSource));
 }
        /// <summary>
        /// Executes the requested overload of <see cref="IDbContextProvider{TDbContext}.ExecuteInDbContextScope{TState, TResult}"/> or its async variant.
        /// </summary>
        private protected async Task <TResult> Execute <TResult>(Overload overload, IDbContextProvider <TestDbContext> provider, Func <IExecutionScope, CancellationToken, Task <TResult> > task,
                                                                 AmbientScopeOption scopeOption      = AmbientScopeOption.JoinExisting,
                                                                 CancellationToken cancellationToken = default)
        {
            switch (overload)
            {
            case Overload.Async:
                await provider.ExecuteInDbContextScopeAsync(WithoutResultWithoutCancellation(task));

                return(default);

            case Overload.AsyncResult:
                return(await provider.ExecuteInDbContextScopeAsync(WithoutCancellation(task)));

            case Overload.Sync:
                provider.ExecuteInDbContextScope(SyncWithoutResult(task));
                return(default);

            case Overload.SyncResult:
                return(provider.ExecuteInDbContextScope(Sync(task)));

            case Overload.AsyncWithScopeOption:
                await provider.ExecuteInDbContextScopeAsync(scopeOption, WithoutResultWithoutCancellation(task));

                return(default);

            case Overload.AsyncResultWithScopeOption:
                return(await provider.ExecuteInDbContextScopeAsync(scopeOption, WithoutCancellation(task)));

            case Overload.SyncWithScopeOption:
                provider.ExecuteInDbContextScope(scopeOption, SyncWithoutResult(task));
                return(default);

            case Overload.SyncResultWithScopeOption:
                return(provider.ExecuteInDbContextScope(scopeOption, Sync(task)));

            case Overload.AsyncWithCancellation:
                await provider.ExecuteInDbContextScopeAsync(cancellationToken, WithoutResult(task));

                return(default);

            case Overload.AsyncResultWithCancellation:
                return(await provider.ExecuteInDbContextScopeAsync(cancellationToken, task));

            case Overload.AsyncWithScopeOptionWithCancellation:
                await provider.ExecuteInDbContextScopeAsync(scopeOption, cancellationToken, WithoutResult(task));

                return(default);

            case Overload.AsyncResultWithScopeOptionWithCancellation:
                return(await provider.ExecuteInDbContextScopeAsync(scopeOption, cancellationToken, task));

            case Overload.AsyncWithState:
                await provider.ExecuteInDbContextScopeAsync(true, cancellationToken, WithoutResult(task));

                return(default);

            case Overload.AsyncResultWithState:
                return(await provider.ExecuteInDbContextScopeAsync(true, cancellationToken, task));

            case Overload.SyncWithState:
                provider.ExecuteInDbContextScope(true, SyncWithoutResult(task));
                return(default);

            case Overload.SyncResultWithState:
                return(provider.ExecuteInDbContextScope(true, Sync(task)));

            case Overload.AsyncWithScopeOptionWithState:
                await provider.ExecuteInDbContextScopeAsync(scopeOption, true, cancellationToken, WithoutResult(task));

                return(default);

            case Overload.AsyncResultWithScopeOptionWithState:
                return(await provider.ExecuteInDbContextScopeAsync(scopeOption, true, cancellationToken, task));

            case Overload.SyncWithScopeOptionWithState:
                provider.ExecuteInDbContextScope(scopeOption, true, SyncWithoutResult(task));
                return(default);

            case Overload.SyncResultWithScopeOptionWithState:
                return(provider.ExecuteInDbContextScope(scopeOption, true, Sync(task)));

            default:
                throw new NotImplementedException();
            }
        }
Пример #20
0
        public static Options <TDbContext> DefaultScopeOption <TDbContext>(this Options <TDbContext> options, AmbientScopeOption defaultScopeOption)
            where TDbContext : DbContext
        {
            if (!Enum.IsDefined(typeof(AmbientScopeOption), defaultScopeOption))
            {
                throw new ArgumentException($"Undefined {nameof(AmbientScopeOption)}: {defaultScopeOption}.");
            }

            options.OptionsBuilder.DefaultScopeOption = defaultScopeOption;
            return(options);
        }
Пример #21
0
 public StaticTestScope(AmbientScopeOption option)
     : base(option)
 {
     this.Index = -1;
 }