/// <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 async Task ExecuteNonQueryAsync( IEnumerable <MigrationCommand> migrationCommands, IRelationalConnection connection, CancellationToken cancellationToken = default) { Check.NotNull(migrationCommands, nameof(migrationCommands)); Check.NotNull(connection, nameof(connection)); var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled); try { await connection.OpenAsync(cancellationToken); try { IDbContextTransaction transaction = null; try { foreach (var command in migrationCommands) { if (transaction == null && !command.TransactionSuppressed) { transaction = await connection.BeginTransactionAsync(cancellationToken); } if (transaction != null && command.TransactionSuppressed) { transaction.Commit(); await transaction.DisposeAsync(); transaction = null; } await command.ExecuteNonQueryAsync(connection, cancellationToken : cancellationToken); } transaction?.Commit(); } finally { if (transaction != null) { await transaction.DisposeAsync(); } } } finally { await connection.CloseAsync(); } } finally { await transactionScope.DisposeAsyncIfAvailable(); } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { var rowsAffected = 0; await connection.OpenAsync(cancellationToken); IDbContextTransaction startedTransaction = null; try { if (connection.CurrentTransaction == null) { startedTransaction = await connection.BeginTransactionAsync(cancellationToken); } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken); rowsAffected += commandbatch.ModificationCommands.Count; } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } return(rowsAffected); }
private async Task ExecuteAsync( IEnumerable <IRelationalCommand> relationalCommands, CancellationToken cancellationToken = default(CancellationToken)) { using (var transaction = await _connection.BeginTransactionAsync(cancellationToken)) { await relationalCommands.ExecuteNonQueryAsync(_connection, cancellationToken); transaction.Commit(); } }
/// <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 async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default) { var rowsAffected = 0; IDbContextTransaction startedTransaction = null; try { if (connection.CurrentTransaction == null && (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null && Transaction.Current == null && CurrentContext.Context.Database.AutoTransactionsEnabled) { startedTransaction = await connection.BeginTransactionAsync(cancellationToken); } else { await connection.OpenAsync(cancellationToken); } foreach (var batch in commandBatches) { await batch.ExecuteAsync(connection, cancellationToken); rowsAffected += batch.ModificationCommands.Count; } if (startedTransaction != null) { await startedTransaction.CommitAsync(cancellationToken); } } finally { if (startedTransaction != null) { await startedTransaction.DisposeAsync(); } else { await connection.CloseAsync(); } } return(rowsAffected); }
/// <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 async Task ExecuteNonQueryAsync( IEnumerable <MigrationCommand> migrationCommands, IRelationalConnection connection, CancellationToken cancellationToken = default) { var userTransaction = connection.CurrentTransaction; if (userTransaction is not null && migrationCommands.Any(x => x.TransactionSuppressed)) { throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction); } var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled); try { await connection.OpenAsync(cancellationToken).ConfigureAwait(false); try { IDbContextTransaction?transaction = null; try { foreach (var command in migrationCommands) { if (transaction == null && !command.TransactionSuppressed && userTransaction is null) { transaction = await connection.BeginTransactionAsync(cancellationToken) .ConfigureAwait(false); } if (transaction != null && command.TransactionSuppressed) { await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); await transaction.DisposeAsync().ConfigureAwait(false); transaction = null; } await command.ExecuteNonQueryAsync(connection, cancellationToken : cancellationToken) .ConfigureAwait(false); } if (transaction != null) { await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); } } finally { if (transaction != null) { await transaction.DisposeAsync().ConfigureAwait(false); } } } finally { await connection.CloseAsync().ConfigureAwait(false); } } finally { await transactionScope.DisposeAsyncIfAvailable().ConfigureAwait(false); } }
/// <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 async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default) { var rowsAffected = 0; var transaction = connection.CurrentTransaction; var beganTransaction = false; var createdSavepoint = false; try { if (transaction == null && (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null && Transaction.Current == null && CurrentContext.Context.Database.AutoTransactionsEnabled) { transaction = await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false); beganTransaction = true; } else { await connection.OpenAsync(cancellationToken).ConfigureAwait(false); if (transaction?.SupportsSavepoints == true && CurrentContext.Context.Database.AutoSavepointsEnabled) { await transaction.CreateSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false); createdSavepoint = true; } } foreach (var batch in commandBatches) { await batch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); rowsAffected += batch.ModificationCommands.Count; } if (beganTransaction) { await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); } } catch { if (createdSavepoint && connection.DbConnection.State == ConnectionState.Open) { try { await transaction.RollbackToSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false); } catch (Exception e) { UpdateLogger.BatchExecutorFailedToRollbackToSavepoint(CurrentContext.GetType(), e); } } throw; } finally { if (beganTransaction) { await transaction.DisposeAsync().ConfigureAwait(false); } else { if (createdSavepoint) { if (connection.DbConnection.State == ConnectionState.Open) { try { await transaction.ReleaseSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false); } catch (Exception e) { UpdateLogger.BatchExecutorFailedToReleaseSavepoint(CurrentContext.GetType(), e); } } } await connection.CloseAsync().ConfigureAwait(false); } } return(rowsAffected); }
/// <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 async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default) { var rowsAffected = 0; var transaction = connection.CurrentTransaction; var beganTransaction = false; var createdSavepoint = false; try { if (transaction == null && (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null && Transaction.Current == null && CurrentContext.Context.Database.AutoTransactionsEnabled) { transaction = await connection.BeginTransactionAsync(cancellationToken); beganTransaction = true; } else { await connection.OpenAsync(cancellationToken); if (transaction?.AreSavepointsSupported == true) { await transaction.SaveAsync(SavepointName, cancellationToken); createdSavepoint = true; } } foreach (var batch in commandBatches) { await batch.ExecuteAsync(connection, cancellationToken); rowsAffected += batch.ModificationCommands.Count; } if (beganTransaction) { await transaction.CommitAsync(cancellationToken); } } catch { if (createdSavepoint) { await transaction.RollbackAsync(SavepointName, cancellationToken); } throw; } finally { if (createdSavepoint) { await transaction.ReleaseAsync(SavepointName, cancellationToken); } else if (beganTransaction) { await transaction.DisposeAsync(); } else { await connection.CloseAsync(); } } return(rowsAffected); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual async Task ExecuteNonQueryAsync( IEnumerable<MigrationCommand> migrationCommands, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(migrationCommands, nameof(migrationCommands)); Check.NotNull(connection, nameof(connection)); await connection.OpenAsync(cancellationToken); try { IDbContextTransaction transaction = null; try { foreach (var command in migrationCommands) { if (transaction == null && !command.TransactionSuppressed) { transaction = await connection.BeginTransactionAsync(cancellationToken); } if (transaction != null && command.TransactionSuppressed) { transaction.Commit(); transaction.Dispose(); transaction = null; } await command.ExecuteNonQueryAsync(connection, cancellationToken: cancellationToken); } transaction?.Commit(); } finally { transaction?.Dispose(); } } finally { connection.Close(); } }