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 = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken); rowsAffected += commandbatch.ModificationCommands.Count; } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } return(rowsAffected); }
public virtual async Task<int> ExecuteAsync( IEnumerable<ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { var rowsAffected = 0; await connection.OpenAsync(cancellationToken); IRelationalTransaction startedTransaction = null; try { if (connection.Transaction == null) { startedTransaction = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken); rowsAffected += commandbatch.ModificationCommands.Count; } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } return rowsAffected; }
public virtual async Task <object> ExecuteAsync( IRelationalConnection connection, Func <Task <object> > action, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open; if (!connectionWasOpen) { Logger.OpeningConnection(connection.ConnectionString); await connection.OpenAsync(cancellationToken); } try { return(await action()); } finally { if (!connectionWasOpen) { Logger.ClosingConnection(connection.ConnectionString); connection.Close(); } } }
protected override async Task <object> ExecuteAsync(IRelationalConnection connection, string executeMethod, IReadOnlyDictionary <string, object> parameterValues, bool closeConnection, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIf.Argument.IsNull(connection, nameof(connection)); ThrowIf.Argument.IsNull(executeMethod, nameof(executeMethod)); var dbCommand = CreateCommand(connection, parameterValues); object result = null; await connection.OpenAsync(cancellationToken); if (executeMethod.Equals(nameof(ExecuteReader))) { try { result = new RelationalDataReader(connection, dbCommand, new MySQLDataReader(await((MySqlCommand)dbCommand).ExecuteReaderAsync(cancellationToken) as MySqlDataReader)); return(result); } catch { dbCommand.Dispose(); throw; } } return(await base.ExecuteAsync(connection, executeMethod, parameterValues, closeConnection, cancellationToken)); }
public virtual async Task ExecuteNonQueryAsync( IRelationalConnection connection, IEnumerable <RelationalCommand> relationalCommands, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); Check.NotNull(relationalCommands, nameof(relationalCommands)); await connection.OpenAsync(cancellationToken); try { foreach (var command in relationalCommands) { await ExecuteAsync( connection, command, async c => await c.ExecuteNonQueryAsync(cancellationToken), cancellationToken); } } finally { connection.Close(); } }
/// <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(); } }
public virtual async Task <object> ExecuteAsync( [NotNull] IRelationalConnection connection, [NotNull] Func <Task <object> > action, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); // TODO Deal with suppressing transactions etc. var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open; if (!connectionWasOpen) { Logger.OpeningConnection(connection.ConnectionString); await connection.OpenAsync(cancellationToken).WithCurrentCulture(); } try { return(await action().WithCurrentCulture()); } finally { if (!connectionWasOpen) { Logger.ClosingConnection(connection.ConnectionString); connection.Close(); } } }
public static async Task ExecuteNonQueryAsync( [NotNull] this IEnumerable <IRelationalCommand> commands, [NotNull] IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(commands, nameof(commands)); Check.NotNull(connection, nameof(connection)); await connection.OpenAsync(cancellationToken); try { foreach (var command in commands) { await command.ExecuteNonQueryAsync( connection, manageConnection : false, cancellationToken : cancellationToken); } } finally { connection.Close(); } }
public virtual async Task <IReadOnlyList <HistoryRow> > GetAppliedMigrationsAsync( CancellationToken cancellationToken = default(CancellationToken)) { var rows = new List <HistoryRow>(); if (await ExistsAsync(cancellationToken)) { await _connection.OpenAsync(cancellationToken); try { using (var reader = await _executor.ExecuteReaderAsync(_connection, GetAppliedMigrationsSql, cancellationToken)) { while (await reader.ReadAsync(cancellationToken)) { rows.Add(new HistoryRow(reader.GetString(0), reader.GetString(1))); } } } finally { _connection.Close(); } } return(rows); }
public async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { var registrosAfetados = 0; await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false); FirebirdSqlRelationalTransaction startedTransaction = null; try { if (connection.CurrentTransaction == null) { startedTransaction = await(connection as FirebirdSqlRelationalConnection).BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as FirebirdSqlRelationalTransaction; } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); registrosAfetados += commandbatch.ModificationCommands.Count; } if (startedTransaction != null) { await startedTransaction.CommitAsync(cancellationToken).ConfigureAwait(false); } startedTransaction?.Dispose(); } catch (Exception err) { try { startedTransaction?.Rollback(); startedTransaction?.Dispose(); } catch { // if the connection was lost, rollback command will fail. prefer to throw original exception in that case } throw err; } finally { connection.Close(); } return(registrosAfetados); }
public async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { var rowsAffected = 0; await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false); MySqlRelationalTransaction startedTransaction = null; try { if (connection.CurrentTransaction == null) { // ReSharper disable once PossibleNullReferenceException startedTransaction = await(connection as MySqlRelationalConnection).BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as MySqlRelationalTransaction; } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); rowsAffected += commandbatch.ModificationCommands.Count; } if (startedTransaction != null) { await startedTransaction.CommitAsync(cancellationToken).ConfigureAwait(false); } startedTransaction?.Dispose(); } catch { try { startedTransaction?.Rollback(); startedTransaction?.Dispose(); } catch { // if the connection was lost, rollback command will fail. prefer to throw original exception in that case } throw; } finally { connection.Close(); } return(rowsAffected); }
public async Task <int> ExecuteAsync( IEnumerable <ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default) { var RowsAffecteds = 0; FbRelationalTransaction currentTransaction = null; try { if (connection?.DbConnection?.State != System.Data.ConnectionState.Open) { await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false); } if (connection.CurrentTransaction == null) { currentTransaction = await((FbRelationalConnection)connection) .BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as FbRelationalTransaction; } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false); RowsAffecteds += commandbatch.ModificationCommands.Count; } if (currentTransaction != null) { await currentTransaction.CommitAsync(cancellationToken).ConfigureAwait(false); } currentTransaction?.Dispose(); } catch (Exception err) { currentTransaction?.Rollback(); currentTransaction?.Dispose(); throw err; } finally { connection?.Close(); } return(RowsAffecteds); }
/// <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 = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken); // Fixed Issue #1: DataReader conflicted when added multiple entities try { lock (this) { var reader = (connection.DbConnection as MySqlConnection).Reader.LastOrDefault(); if (reader != null) { reader.Dispose(); (connection.DbConnection as MySqlConnection).Reader.Remove(reader); } } } catch { } rowsAffected += commandbatch.ModificationCommands.Count; } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } 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; 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 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(); } }
/// <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 = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { await commandbatch.ExecuteAsync(connection, cancellationToken); // Fixed Issue #1: DataReader conflicted when added multiple entities try { lock(this) { var reader = (connection.DbConnection as MySqlConnection).Reader.LastOrDefault(); if (reader != null) { reader.Dispose(); (connection.DbConnection as MySqlConnection).Reader.Remove(reader); } } } catch { } rowsAffected += commandbatch.ModificationCommands.Count; } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } return rowsAffected; }
protected virtual async Task <object> ExecuteAsync( IRelationalConnection connection, Func <Task <object> > action, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); await connection.OpenAsync(cancellationToken); try { return(await action()); } finally { connection.Close(); } }
protected virtual async Task<object> ExecuteAsync( IRelationalConnection connection, Func<Task<object>> action, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); await connection.OpenAsync(cancellationToken); try { return await action(); } finally { connection.Close(); } }
public virtual async Task <int> ExecuteAsync( [NotNull] IEnumerable <ModificationCommandBatch> commandBatches, [NotNull] IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(commandBatches, nameof(commandBatches)); Check.NotNull(connection, nameof(connection)); var rowsAffected = 0; await connection.OpenAsync(cancellationToken).WithCurrentCulture(); RelationalTransaction startedTransaction = null; try { if (connection.Transaction == null) { startedTransaction = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { rowsAffected += await commandbatch.ExecuteAsync( connection.Transaction, _typeMapper, _context, Logger, cancellationToken) .WithCurrentCulture(); } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } return(rowsAffected); }
protected virtual async Task <T> ExecuteAsync <T>( [NotNull] IRelationalConnection connection, [NotNull] RelationalCommand command, [NotNull] Func <DbCommand, Task <T> > action, CancellationToken cancellationToken = default(CancellationToken)) { await connection.OpenAsync(cancellationToken); try { using (var dbCommand = command.CreateCommand(connection)) { Logger.LogCommand(dbCommand); return(await action(dbCommand)); } } finally { connection.Close(); } }
public virtual async Task<int> ExecuteAsync( IEnumerable<ModificationCommandBatch> commandBatches, IRelationalConnection connection, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(commandBatches, nameof(commandBatches)); Check.NotNull(connection, nameof(connection)); var rowsAffected = 0; await connection.OpenAsync(cancellationToken); RelationalTransaction startedTransaction = null; try { if (connection.Transaction == null) { startedTransaction = connection.BeginTransaction(); } foreach (var commandbatch in commandBatches) { rowsAffected += await commandbatch.ExecuteAsync( connection.Transaction, _typeMapper, _context, Logger, cancellationToken); } startedTransaction?.Commit(); } finally { startedTransaction?.Dispose(); connection.Close(); } 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> protected virtual async Task <object> ExecuteAsync( [NotNull] IRelationalConnection connection, [NotNull] string executeMethod, [CanBeNull] IReadOnlyDictionary <string, object> parameterValues, bool closeConnection = true, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); Check.NotEmpty(executeMethod, nameof(executeMethod)); var dbCommand = CreateCommand(connection, parameterValues); await connection.OpenAsync(cancellationToken); var startTimestamp = Stopwatch.GetTimestamp(); var instanceId = Guid.NewGuid(); DiagnosticSource.WriteCommandBefore( dbCommand, executeMethod, instanceId, startTimestamp, async: true); object result; try { switch (executeMethod) { case nameof(ExecuteNonQuery): { using (dbCommand) { result = await dbCommand.ExecuteNonQueryAsync(cancellationToken); } break; } case nameof(ExecuteScalar): { using (dbCommand) { result = await dbCommand.ExecuteScalarAsync(cancellationToken); } break; } case nameof(ExecuteReader): { try { result = new RelationalDataReader( connection, dbCommand, await dbCommand.ExecuteReaderAsync(cancellationToken)); } catch { dbCommand.Dispose(); throw; } break; } default: { throw new NotSupportedException(); } } var currentTimestamp = Stopwatch.GetTimestamp(); Logger.LogCommandExecuted(dbCommand, startTimestamp, currentTimestamp); DiagnosticSource.WriteCommandAfter( dbCommand, executeMethod, instanceId, startTimestamp, currentTimestamp, async: true); if (closeConnection) { connection.Close(); } } catch (Exception exception) { var currentTimestamp = Stopwatch.GetTimestamp(); Logger.LogCommandExecuted(dbCommand, startTimestamp, currentTimestamp); DiagnosticSource.WriteCommandError( dbCommand, executeMethod, instanceId, startTimestamp, currentTimestamp, exception, async: true); connection.Close(); throw; } finally { dbCommand.Parameters.Clear(); } return(result); }
/// <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> /// The method called by other methods on this type to execute synchronously. /// </summary> /// <param name="connection"> The connection to use. </param> /// <param name="executeMethod"> The method type. </param> /// <param name="parameterValues"> The parameter values. </param> /// <param name="logger"> The command logger. </param> /// <param name="cancellationToken"> The cancellation token. </param> /// <returns> The result of the execution. </returns> protected virtual async Task <object> ExecuteAsync( [NotNull] IRelationalConnection connection, DbCommandMethod executeMethod, [CanBeNull] IReadOnlyDictionary <string, object> parameterValues, [CanBeNull] IDiagnosticsLogger <DbLoggerCategory.Database.Command> logger, CancellationToken cancellationToken = default) { Check.NotNull(connection, nameof(connection)); var dbCommand = CreateCommand(connection, parameterValues); await connection.OpenAsync(cancellationToken); var commandId = Guid.NewGuid(); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); logger?.CommandExecuting( dbCommand, executeMethod, commandId, connection.ConnectionId, async: true, startTime: startTime); object result; var readerOpen = false; try { switch (executeMethod) { case DbCommandMethod.ExecuteNonQuery: { result = await dbCommand.ExecuteNonQueryAsync(cancellationToken); break; } case DbCommandMethod.ExecuteScalar: { result = await dbCommand.ExecuteScalarAsync(cancellationToken); break; } case DbCommandMethod.ExecuteReader: { result = new RelationalDataReader( connection, dbCommand, await dbCommand.ExecuteReaderAsync(cancellationToken), commandId, logger); readerOpen = true; break; } default: { throw new NotSupportedException(); } } logger?.CommandExecuted( dbCommand, executeMethod, commandId, connection.ConnectionId, result, true, startTime, stopwatch.Elapsed); } catch (Exception exception) { logger?.CommandError( dbCommand, executeMethod, commandId, connection.ConnectionId, exception, true, startTime, stopwatch.Elapsed); throw; } finally { if (!readerOpen) { dbCommand.Parameters.Clear(); dbCommand.Dispose(); connection.Close(); } } return(result); }
protected virtual async Task <object> ExecuteAsync( [NotNull] IRelationalConnection connection, [NotNull] string executeMethod, bool openConnection, bool closeConnection, CancellationToken cancellationToken = default(CancellationToken), [CanBeNull] IReadOnlyDictionary <string, object> parameterValues = null) { var dbCommand = CreateCommand(connection, parameterValues); WriteDiagnostic( RelationalDiagnostics.BeforeExecuteCommand, dbCommand, executeMethod, async: true); object result; if (openConnection) { await connection.OpenAsync(cancellationToken); } Stopwatch stopwatch = null; try { if (Logger.IsEnabled(LogLevel.Information)) { stopwatch = Stopwatch.StartNew(); } switch (executeMethod) { case nameof(ExecuteNonQuery): { using (dbCommand) { result = await dbCommand.ExecuteNonQueryAsync(cancellationToken); } break; } case nameof(ExecuteScalar): { using (dbCommand) { result = await dbCommand.ExecuteScalarAsync(cancellationToken); } break; } case nameof(ExecuteReader): { try { result = new RelationalDataReader( openConnection ? connection : null, dbCommand, await dbCommand.ExecuteReaderAsync(cancellationToken)); } catch { dbCommand.Dispose(); throw; } break; } default: { throw new NotSupportedException(); } } stopwatch?.Stop(); Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds); } catch (Exception exception) { stopwatch?.Stop(); Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds); DiagnosticSource .WriteCommandError( dbCommand, executeMethod, async: true, exception: exception); if (openConnection && !closeConnection) { connection.Close(); } throw; } finally { if (closeConnection) { connection.Close(); } } WriteDiagnostic( RelationalDiagnostics.AfterExecuteCommand, dbCommand, executeMethod, async: true); return(result); }
/// <summary> /// 异步执行 /// </summary> /// <param name="connection"></param> /// <param name="executeMethod"></param> /// <param name="parameterValues"></param> /// <param name="cancellationToken"></param> /// <returns></returns> protected override async Task <object> ExecuteAsync(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary <string, object> parameterValues, CancellationToken cancellationToken = default(CancellationToken)) { if (Check.IsTraceEnabled(Logger?.Logger)) { Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Trace, OracleTraceTag.Entry, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync); } Check.NotNull(connection, nameof(connection)); // 创建命令并打开连接 DbCommand dbCommand = CreateCommand(connection, parameterValues); await connection.OpenAsync(cancellationToken); Guid commandId = Guid.NewGuid(); DateTimeOffset startTime = DateTimeOffset.UtcNow; Stopwatch stopwatch = Stopwatch.StartNew(); // 执行命令 Logger.CommandExecuting(dbCommand, executeMethod, commandId, connection.ConnectionId, async: true, startTime); // 读取数据 bool readerOpen = false; try { object obj; switch (executeMethod) { case DbCommandMethod.ExecuteNonQuery: obj = await dbCommand.ExecuteNonQueryAsync(cancellationToken); break; case DbCommandMethod.ExecuteScalar: obj = await dbCommand.ExecuteScalarAsync(cancellationToken); break; case DbCommandMethod.ExecuteReader: { DbCommand command = dbCommand; obj = new RelationalDataReader(connection, command, await dbCommand.ExecuteReaderAsync(cancellationToken), commandId, Logger); readerOpen = true; break; } default: throw new NotSupportedException(); } Logger.CommandExecuted(dbCommand, executeMethod, commandId, connection.ConnectionId, obj, async: true, startTime, stopwatch.Elapsed); return(obj); } catch (Exception ex) { if (Check.IsErrorEnabled(Logger?.Logger)) { Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync, ex.ToString()); } Logger.CommandError(dbCommand, executeMethod, commandId, connection.ConnectionId, ex, async: true, startTime, stopwatch.Elapsed); throw; } finally { if (!readerOpen) { dbCommand.Dispose(); connection.Close(); } dbCommand.Parameters.Clear(); if (Check.IsTraceEnabled(Logger?.Logger)) { Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Trace, OracleTraceTag.Exit, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync); } } }
private async Task <object> ExecuteAsync( IOBehavior ioBehavior, [NotNull] IRelationalConnection connection, [NotNull] string executeMethod, [CanBeNull] IReadOnlyDictionary <string, object> parameterValues, bool openConnection, bool closeConnection, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); Check.NotEmpty(executeMethod, nameof(executeMethod)); var dbCommand = CreateCommand(connection, parameterValues); object result; if (openConnection) { if (ioBehavior == IOBehavior.Asynchronous) { await connection.OpenAsync(cancellationToken).ConfigureAwait(false); } else { connection.Open(); } } cancellationToken.ThrowIfCancellationRequested(); var mySqlConnection = connection as MySqlRelationalConnection; var locked = false; try { if (ioBehavior == IOBehavior.Asynchronous) { // ReSharper disable once PossibleNullReferenceException await mySqlConnection.PoolingOpenAsync(cancellationToken).ConfigureAwait(false); await mySqlConnection.Lock.WaitAsync(cancellationToken).ConfigureAwait(false); } else { // ReSharper disable once PossibleNullReferenceException mySqlConnection.PoolingOpen(); mySqlConnection.Lock.Wait(cancellationToken); } locked = true; switch (executeMethod) { case nameof(ExecuteNonQuery): { using (dbCommand) { if (ioBehavior == IOBehavior.Asynchronous) { result = await dbCommand.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false); } else { result = dbCommand.ExecuteNonQuery(); } } break; } case nameof(ExecuteScalar): { using (dbCommand) { if (ioBehavior == IOBehavior.Asynchronous) { result = await dbCommand.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); } else { result = dbCommand.ExecuteScalar(); } } break; } case nameof(ExecuteReader): { try { MySqlDataReader dataReader; if (ioBehavior == IOBehavior.Asynchronous) { dataReader = await dbCommand.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false) as MySqlDataReader; } else { dataReader = dbCommand.ExecuteReader() as MySqlDataReader; } result = new RelationalDataReader(openConnection ? connection : null, dbCommand, new SynchronizedMySqlDataReader(dataReader, mySqlConnection)); } catch (Exception) { dbCommand.Dispose(); throw; } break; } default: { throw new NotSupportedException(); } } } catch (Exception) { if (openConnection && !closeConnection) { connection.Close(); } throw; } finally { if (closeConnection) { connection.Close(); } if (locked && executeMethod != nameof(ExecuteReader)) { // if calling any other method, the command has finished executing and the lock can be released immediately // ReSharper disable once PossibleNullReferenceException mySqlConnection.Lock.Release(); mySqlConnection.PoolingClose(); } } return(result); }
public virtual async Task<object> ExecuteAsync( IRelationalConnection connection, Func<Task<object>> action, CancellationToken cancellationToken = default(CancellationToken)) { Check.NotNull(connection, nameof(connection)); var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open; if (!connectionWasOpen) { Logger.OpeningConnection(connection.ConnectionString); await connection.OpenAsync(cancellationToken); } try { return await action(); } finally { if (!connectionWasOpen) { Logger.ClosingConnection(connection.ConnectionString); connection.Close(); } } }
/// <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); } }
// TODO: Copy and paste base code again in 3.0. // Then replace "RelationalDataReader" with "MySqlConverterRelationalDataReader". // TODO: Remove entire method in 3.1. // Replace with overridden implementation of "CreateRelationalDataReader". /// <summary> /// Uses the same code as in it's base class, except for returning a /// ConverterRelationalDataReader instead of a RelationalDataReader. /// </summary> protected override async Task <object> ExecuteAsync( IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary <string, object> parameterValues, CancellationToken cancellationToken = default) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } var dbCommand = CreateCommand(connection, parameterValues); await connection.OpenAsync(cancellationToken); var commandId = Guid.NewGuid(); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); Logger.CommandExecuting( dbCommand, executeMethod, commandId, connection.ConnectionId, async: true, startTime: startTime); object result; var readerOpen = false; try { switch (executeMethod) { case DbCommandMethod.ExecuteNonQuery: { result = await dbCommand.ExecuteNonQueryAsync(cancellationToken); break; } case DbCommandMethod.ExecuteScalar: { result = await dbCommand.ExecuteScalarAsync(cancellationToken); break; } case DbCommandMethod.ExecuteReader: { result = new MySqlConverterRelationalDataReader( connection, dbCommand, await dbCommand.ExecuteReaderAsync(cancellationToken), commandId, Logger); readerOpen = true; break; } default: { throw new NotSupportedException(); } } Logger.CommandExecuted( dbCommand, executeMethod, commandId, connection.ConnectionId, result, true, startTime, stopwatch.Elapsed); } catch (Exception exception) { Logger.CommandError( dbCommand, executeMethod, commandId, connection.ConnectionId, exception, true, startTime, stopwatch.Elapsed); throw; } finally { if (!readerOpen) { dbCommand.Parameters.Clear(); dbCommand.Dispose(); connection.Close(); } } return(result); }
protected virtual async Task <T> ExecuteAsync <T>( [NotNull] IRelationalConnection connection, [NotNull] Func <DbCommand, IRelationalConnection, CancellationToken, Task <T> > action, [NotNull] string executeMethod, bool openConnection, bool closeConnection, CancellationToken cancellationToken = default(CancellationToken)) { var dbCommand = CreateCommand(connection); WriteDiagnostic( RelationalDiagnostics.BeforeExecuteCommand, dbCommand, executeMethod, async: true); T result; if (openConnection) { await connection.OpenAsync(cancellationToken); } Stopwatch stopwatch = null; try { if (Logger.IsEnabled(LogLevel.Information)) { stopwatch = Stopwatch.StartNew(); } result = await action(dbCommand, connection, cancellationToken); stopwatch?.Stop(); Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds); } catch (Exception exception) { stopwatch?.Stop(); Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds); DiagnosticSource .WriteCommandError( dbCommand, executeMethod, async: true, exception: exception); if (openConnection && !closeConnection) { connection.Close(); } throw; } finally { if (closeConnection) { connection.Close(); } } WriteDiagnostic( RelationalDiagnostics.AfterExecuteCommand, dbCommand, executeMethod, async: true); return(result); }