2014-09-22 43 views
2

我越來越感興趣的錯誤,我想修復。這裏是我的課,SqlDataReader已經在不同的命令打開

public class SqlCommandWrapper 
{ 
    private readonly ISettings _settings; 
    private readonly ILogger _logger; 

    public SqlCommandWrapper(ISettings settings, ILogger logger) 
    { 
     _settings = settings; 
     _logger = logger; 
    } 

    private enum ExecutionType 
    { 
     Reader, 
     NonQuery, 
     Scaler 

    } 

    public async Task<SqlDataReader> ExecuteReaderAsync(string commandText, params SqlParameter[] parameters) 
    { 
     return (SqlDataReader)await ExecuteAsync(ExecutionType.Reader, CommandType.StoredProcedure, commandText, IsolationLevel.ReadUncommitted, parameters).ConfigureAwait(false); 
    } 

    public async Task<SqlDataReader> ExecuteReaderAsync(CommandType commandType, string commandText, IsolationLevel isolationLevel, 
     params SqlParameter[] parameters) 
    { 
     return (SqlDataReader)await ExecuteAsync(ExecutionType.Reader, commandType, commandText, isolationLevel, parameters).ConfigureAwait(false); 
    } 

    public async Task<SqlDataReader> ExecuteReaderAsync(CommandType commandType, string commandText, params SqlParameter[] parameters) 
    { 
     return 
      (SqlDataReader) 
       await ExecuteAsync(ExecutionType.Reader, commandType, commandText, IsolationLevel.ReadUncommitted, parameters).ConfigureAwait(false); 
    } 

    public async Task<int> ExecuteNonQueryAsync(string commandText, params SqlParameter[] parameters) 
    { 
     return (int)await ExecuteAsync(ExecutionType.NonQuery, CommandType.StoredProcedure, commandText, IsolationLevel.ReadUncommitted, parameters).ConfigureAwait(false); 
    } 

    public async Task<int> ExecuteNonQueryAsync(CommandType commandType, string commandText, IsolationLevel isolationLevel, params SqlParameter[] parameters) 
    { 
     return (int) await ExecuteAsync(ExecutionType.NonQuery, commandType, commandText, isolationLevel, parameters).ConfigureAwait(false); 
    } 

    public async Task<int> ExecuteNonQueryAsync(CommandType commandType, string commandText, params SqlParameter[] parameters) 
    { 
     return (int) await ExecuteAsync(ExecutionType.NonQuery, commandType, commandText, IsolationLevel.ReadUncommitted, parameters).ConfigureAwait(false); 
    } 

    public Task<object> ExecuteScalarAsync(string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteAsync(ExecutionType.Scaler, CommandType.StoredProcedure, commandText, IsolationLevel.ReadUncommitted, parameters); 
    } 

    public Task<object> ExecuteScalarAsync(CommandType commandType, string commandText, IsolationLevel isolationLevel, params SqlParameter[] parameters) 
    { 
     return ExecuteAsync(ExecutionType.Scaler, commandType, commandText, isolationLevel, parameters); 
    } 

    public Task<object> ExecuteScalarAsync(CommandType commandType, string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteAsync(ExecutionType.Scaler, commandType, commandText, IsolationLevel.ReadUncommitted, parameters); 
    } 


    private async Task<object> ExecuteAsync(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, 
     params SqlParameter[] parameters) 
    { 
     using (var connection = new SqlConnection(_settings.DatabaseConnectionString)) 
     { 
      using (var command = new SqlCommand(commandText, connection) {CommandType = commandType}) 
      { 
       command.Parameters.AddRange(parameters); 
       command.CommandTimeout = _settings.CommandTimeout; 
       await connection.OpenAsync().ConfigureAwait(false); 
       var transaction = connection.BeginTransaction(isolationLevel); 
       command.Transaction = transaction; 
       try 
       { 
        object result; 
        switch (executionType) 
        { 
         case ExecutionType.Reader: 
          result = await command.ExecuteReaderAsync().ConfigureAwait(false); 
          break; 
         case ExecutionType.NonQuery: 
          result = await command.ExecuteNonQueryAsync().ConfigureAwait(false); 
          break; 
         default: 
          result = await command.ExecuteScalarAsync().ConfigureAwait(false); 
          break; 
        } 
        transaction.Commit(); 
        return result; 
       } 
       catch (Exception exception) 
       { 
        _logger.Log(exception); 
        transaction.Rollback(); 
        throw; 
       } 
      } 
     } 
    } 
} 

,我使用調用此,

using (var reader = await _sqlCommandWrapper.ExecuteReaderAsync("MySP", parameters)) 
{ 
    // My code 
} 

當我跑我的課,我得到一個錯誤:

There is already an open DataReader associated with this Command which must be closed first.

+2

我認爲問題在於該方法試圖返回一個開放的數據讀取器,但同時它試圖提交事務並在返回之前處理命令和連接對象。你無法完成這兩個目標。 – 2014-09-22 14:17:30

+0

@Damien_The_Unbeliever,不,我只是獲取數據。 – user960567 2014-09-22 14:18:36

+3

不,您不僅僅是「獲取數據」 - 您的方法正在返回一個'SqlDataReader' - 其中沒有數據尚未讀取且仍處於打開狀態的數據。 – 2014-09-22 14:21:16

回答

1

我加入了修復回撥方式,

public class SqlCommandWrapper 
{ 
    private readonly ISettings _settings; 
    private readonly ILogger _logger; 

    public SqlCommandWrapper(ISettings settings, ILogger logger) 
    { 
     _settings = settings; 
     _logger = logger; 
    } 

    public enum ExecutionType 
    { 
     Reader, 
     NonQuery, 
     Scaler 
    } 

    public Task<IEnumerable<T>> ExecuteReaderAsync<T>(string commandText, Func<IDataReader, T> callback, params SqlParameter[] parameters) 
    { 
     return ExecuteReaderAsync(CommandType.StoredProcedure, commandText, callback, parameters); 
    } 

    public Task<IEnumerable<T>> ExecuteReaderAsync<T>(CommandType commandType, string commandText, Func<IDataReader, T> callback, params SqlParameter[] parameters) 
    { 
     return ExecuteReaderAsync(ExecutionType.Reader, commandType, commandText, IsolationLevel.ReadUncommitted, callback, parameters); 
    } 

    public async Task<IEnumerable<T>> ExecuteReaderAsync<T>(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, 
     Func<IDataReader, T> callback, params SqlParameter[] parameters) 
    { 
     return (IEnumerable<T>)await ExecuteAsync(executionType, commandType, commandText, isolationLevel, parameters, callback).ConfigureAwait(false); 
    } 

    public Task<int> ExecuteNonQueryAsync(string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteNonQueryAsync(CommandType.StoredProcedure, commandText, parameters); 
    } 

    public Task<int> ExecuteNonQueryAsync(CommandType commandType, string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteNonQueryAsync(ExecutionType.NonQuery, commandType, commandText, IsolationLevel.ReadUncommitted, parameters); 
    } 

    public async Task<int> ExecuteNonQueryAsync(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, params SqlParameter[] parameters) 
    { 
     return (int)await ExecuteAsync(executionType, commandType, commandText, isolationLevel, parameters).ConfigureAwait(false); 
    } 

    public Task<object> ExecuteScalarAsync(string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteScalarAsync(CommandType.StoredProcedure, commandText, parameters); 
    } 

    public Task<object> ExecuteScalarAsync(CommandType commandType, string commandText, params SqlParameter[] parameters) 
    { 
     return ExecuteScalarAsync(ExecutionType.Scaler, commandType, commandText, IsolationLevel.ReadUncommitted, parameters); 
    } 

    public Task<object> ExecuteScalarAsync(ExecutionType executionType,CommandType commandType, string commandText, IsolationLevel isolationLevel, params SqlParameter[] parameters) 
    { 
     return ExecuteAsync(executionType, commandType, commandText, isolationLevel, parameters); 
    } 

    private Task<object> ExecuteAsync(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, 
     SqlParameter[] parameters) 
    { 
     return ExecuteAsync<object>(executionType, commandType, commandText, isolationLevel, parameters); 
    } 

    private async Task<object> ExecuteAsync<T>(ExecutionType executionType, CommandType commandType, string commandText, IsolationLevel isolationLevel, SqlParameter[] parameters, Func<IDataReader, T> callback = null) 
    { 
     using (var connection = new SqlConnection(_settings.DatabaseConnectionString)) 
     { 
      using (var command = new SqlCommand(commandText, connection) {CommandType = commandType}) 
      { 
       command.Parameters.AddRange(parameters); 
       command.CommandTimeout = _settings.CommandTimeout; 
       await connection.OpenAsync().ConfigureAwait(false); 
       var transaction = connection.BeginTransaction(isolationLevel); 
       command.Transaction = transaction; 
       try 
       { 
        object result; 
        switch (executionType) 
        { 
         case ExecutionType.Reader: 
          var reader = await command.ExecuteReaderAsync().ConfigureAwait(false); 
          using (reader) 
          { 
           var list = new List<T>(); 
           while (reader.Read()) 
           { 
            if (callback != null) 
            { 
             list.Add(callback(reader)); 
            } 
           } 
           result = list; 
          } 
          break; 
         case ExecutionType.NonQuery: 
          result = await command.ExecuteNonQueryAsync().ConfigureAwait(false); 
          break; 
         default: 
          result = await command.ExecuteScalarAsync().ConfigureAwait(false); 
          break; 
        } 
        transaction.Commit(); 
        return result; 
       } 
       catch (Exception exception) 
       { 
        _logger.Log(exception); 
        transaction.Rollback(); 
        throw; 
       } 
      } 
     } 
    } 
} 

用法,

(await _sqlCommandWrapper.ExecuteReaderAsync("MySP", r => 
      new Product 
      { 
       Id = (int) r["Id"], 
       ........................ 
       ........................ 
       ........................ 

      }, parameters)).ToList() 
相關問題