Skip to content

Commit

Permalink
Allow providers to override HandleAmbientTransactions (#24209)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Feb 25, 2021
1 parent 35a19f8 commit 083042b
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ public virtual void RollbackTransaction()
public virtual Task RollbackTransactionAsync(CancellationToken cancellationToken = default)
=> throw new NotSupportedException(CosmosStrings.TransactionsNotSupported);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Transaction CurrentAmbientTransaction
=> null;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down
9 changes: 7 additions & 2 deletions src/EFCore.Relational/Storage/RelationalConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,11 @@ public virtual DbConnection DbConnection
}
}

/// <summary>
/// The current ambient transaction. Defaults to <see cref="Transaction.Current" />.
/// </summary>
public virtual Transaction? CurrentAmbientTransaction => Transaction.Current;

/// <summary>
/// Gets the current transaction.
/// </summary>
Expand Down Expand Up @@ -397,7 +402,7 @@ private void EnsureNoTransactions()
throw new InvalidOperationException(RelationalStrings.TransactionAlreadyStarted);
}

if (Transaction.Current != null)
if (CurrentAmbientTransaction != null)
{
throw new InvalidOperationException(RelationalStrings.ConflictingAmbientTransaction);
}
Expand Down Expand Up @@ -748,7 +753,7 @@ protected virtual Task OpenDbConnectionAsync(bool errorsExpected, CancellationTo

private void HandleAmbientTransactions()
{
var current = Transaction.Current;
var current = CurrentAmbientTransaction;

if (current == null)
{
Expand Down
12 changes: 7 additions & 5 deletions src/EFCore.Relational/Update/Internal/BatchExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ public virtual int Execute(
var createdSavepoint = false;
try
{
var transactionEnlistManager = connection as ITransactionEnlistmentManager;
if (transaction == null
&& (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null
&& Transaction.Current == null
&& CurrentContext.Context.Database.AutoTransactionsEnabled)
&& transactionEnlistManager?.EnlistedTransaction is null
&& transactionEnlistManager?.CurrentAmbientTransaction is null
&& CurrentContext.Context.Database.AutoTransactionsEnabled)
{
transaction = connection.BeginTransaction();
beganTransaction = true;
Expand Down Expand Up @@ -170,9 +171,10 @@ public virtual async Task<int> ExecuteAsync(
var createdSavepoint = false;
try
{
var transactionEnlistManager = connection as ITransactionEnlistmentManager;
if (transaction == null
&& (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null
&& Transaction.Current == null
&& transactionEnlistManager?.EnlistedTransaction is null
&& transactionEnlistManager?.CurrentAmbientTransaction is null
&& CurrentContext.Context.Database.AutoTransactionsEnabled)
{
transaction = await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false);
Expand Down
7 changes: 4 additions & 3 deletions src/EFCore/Storage/ExecutionStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,10 @@ private async Task<ExecutionResult<TResult>> ExecuteImplementationAsync<TState,
/// </summary>
protected virtual void OnFirstExecution()
{
if (Dependencies.CurrentContext.Context.Database.CurrentTransaction != null
|| Dependencies.CurrentContext.Context.Database.GetEnlistedTransaction() != null
|| Transaction.Current != null)
if (Dependencies.CurrentContext.Context.Database.CurrentTransaction is not null
|| Dependencies.CurrentContext.Context.Database.GetEnlistedTransaction() is not null
|| (((IDatabaseFacadeDependenciesAccessor)Dependencies.CurrentContext.Context.Database).Dependencies.TransactionManager as
ITransactionEnlistmentManager)?.CurrentAmbientTransaction is not null)
{
throw new InvalidOperationException(
CoreStrings.ExecutionStrategyExistingTransaction(
Expand Down
5 changes: 5 additions & 0 deletions src/EFCore/Storage/ITransactionEnlistmentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ namespace Microsoft.EntityFrameworkCore.Storage
/// </summary>
public interface ITransactionEnlistmentManager
{
/// <summary>
/// The current ambient transaction. Defaults to <see cref="Transaction.Current" />.
/// </summary>
Transaction? CurrentAmbientTransaction => Transaction.Current;

/// <summary>
/// The currently enlisted transaction.
/// </summary>
Expand Down

0 comments on commit 083042b

Please sign in to comment.