/// <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); }
/// <summary> /// Executes the command with a <see cref="RelationalDataReader" /> result. /// </summary> /// <param name="parameterObject"> Parameters for this method. </param> /// <returns> The result of the command. </returns> public virtual RelationalDataReader ExecuteReader(RelationalCommandParameterObject parameterObject) { var(connection, context, logger) = (parameterObject.Connection, parameterObject.Context, parameterObject.Logger); var commandId = Guid.NewGuid(); var command = CreateCommand(parameterObject, commandId, DbCommandMethod.ExecuteReader); connection.Open(); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); var readerOpen = false; try { var interceptionResult = logger?.CommandReaderExecuting( connection, command, context, commandId, connection.ConnectionId, startTime) ?? default; var reader = interceptionResult.HasResult ? interceptionResult.Result : command.ExecuteReader(); if (logger != null) { reader = logger.CommandReaderExecuted( connection, command, context, commandId, connection.ConnectionId, reader, startTime, stopwatch.Elapsed); } var result = new RelationalDataReader( connection, command, reader, commandId, logger); readerOpen = true; return(result); } catch (Exception exception) { logger?.CommandError( connection, command, context, DbCommandMethod.ExecuteReader, commandId, connection.ConnectionId, exception, startTime, stopwatch.Elapsed); throw; } finally { if (!readerOpen) { CleanupCommand(command, connection); } } }
/// <summary> /// Asynchronously executes the command with a <see cref="RelationalDataReader" /> result. /// </summary> /// <param name="parameterObject"> Parameters for this method. </param> /// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param> /// <returns> /// A task that represents the asynchronous operation. The task result contains the result of the command. /// </returns> public virtual async Task <RelationalDataReader> ExecuteReaderAsync( RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken = default) { var(connection, context, logger) = (parameterObject.Connection, parameterObject.Context, parameterObject.Logger); var commandId = Guid.NewGuid(); var command = CreateCommand(parameterObject, commandId, DbCommandMethod.ExecuteReader); await connection.OpenAsync(cancellationToken); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); var readerOpen = false; try { var interceptionResult = logger == null ? default : await logger.CommandReaderExecutingAsync( connection, command, context, commandId, connection.ConnectionId, startTime, cancellationToken); var reader = interceptionResult.HasResult ? interceptionResult.Result : await command.ExecuteReaderAsync(cancellationToken); if (logger != null) { reader = await logger.CommandReaderExecutedAsync( connection, command, context, commandId, connection.ConnectionId, reader, startTime, stopwatch.Elapsed, cancellationToken); } var result = new RelationalDataReader( connection, command, reader, commandId, logger); readerOpen = true; return(result); } catch (Exception exception) { if (logger != null) { await logger.CommandErrorAsync( connection, command, context, DbCommandMethod.ExecuteReader, commandId, connection.ConnectionId, exception, startTime, stopwatch.Elapsed, cancellationToken); } throw; } finally { if (!readerOpen) { await CleanupCommandAsync(command, connection); } } }
/// <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> /// <returns> The result of the execution. </returns> protected virtual object Execute( [NotNull] IRelationalConnection connection, DbCommandMethod executeMethod, [CanBeNull] IReadOnlyDictionary <string, object> parameterValues, [CanBeNull] IDiagnosticsLogger <DbLoggerCategory.Database.Command> logger) { Check.NotNull(connection, nameof(connection)); var dbCommand = CreateCommand(connection, parameterValues); connection.Open(); var commandId = Guid.NewGuid(); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); object result; var readerOpen = false; try { switch (executeMethod) { case DbCommandMethod.ExecuteNonQuery: var nonQueryResult = (logger?.CommandNonQueryExecuting( dbCommand, commandId, connection.ConnectionId, startTime: startTime) ?? new InterceptionResult <int>(dbCommand.ExecuteNonQuery())).Result; result = logger?.CommandNonQueryExecuted( dbCommand, commandId, connection.ConnectionId, nonQueryResult, startTime, stopwatch.Elapsed) ?? nonQueryResult; break; case DbCommandMethod.ExecuteScalar: var scalarResult = (logger?.CommandScalarExecuting( dbCommand, commandId, connection.ConnectionId, startTime: startTime) ?? new InterceptionResult <object>(dbCommand.ExecuteScalar())).Result; result = logger?.CommandScalarExecuted( dbCommand, commandId, connection.ConnectionId, scalarResult, startTime, stopwatch.Elapsed) ?? scalarResult; break; case DbCommandMethod.ExecuteReader: var reader = (logger?.CommandReaderExecuting( dbCommand, commandId, connection.ConnectionId, startTime: startTime) ?? new InterceptionResult <DbDataReader>(dbCommand.ExecuteReader())).Result; if (logger != null) { reader = logger?.CommandReaderExecuted( dbCommand, commandId, connection.ConnectionId, reader, startTime, stopwatch.Elapsed); } result = new RelationalDataReader( connection, dbCommand, reader, commandId, logger); readerOpen = true; break; default: throw new NotSupportedException(); } } catch (Exception exception) { logger?.CommandError( dbCommand, executeMethod, commandId, connection.ConnectionId, exception, false, startTime, stopwatch.Elapsed); throw; } finally { if (!readerOpen) { dbCommand.Parameters.Clear(); dbCommand.Dispose(); connection.Close(); } } return(result); }