public TResult ExecuteComplex <TResult>(Action <DbCommand> initializer, Func <DbDataReader, TResult> materializer) { if (unbufferedReader != null) { unbufferedReader.Buffer(); unbufferedReader = null; } var result = default(object); var connection = CurrentDbContext.Context.Database.GetService <IRelationalConnection>(); connection.Open(); using (var command = CreateCommand(connection)) { initializer(command); var commandId = Guid.NewGuid(); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); logger.CommandExecuting( command, DbCommandMethod.ExecuteReader, commandId, connection.ConnectionId, false, startTime); try { using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection)) { logger.CommandExecuted( command, DbCommandMethod.ExecuteReader, commandId, connection.ConnectionId, result, false, startTime, stopwatch.Elapsed); reader.Read(); CurrentDbContext.GetDependencies().StateManager.BeginTrackingQuery(); return(materializer(reader)); } } catch (Exception exception) { logger.CommandError( command, DbCommandMethod.ExecuteReader, commandId, connection.ConnectionId, exception, false, startTime, stopwatch.Elapsed); throw; } finally { connection.Close(); } } }
/// <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); }