2015-03-10 3 views
0

Я получаю следующую ошибку с перерывами. Уже открыт DataReader, связанный с этой Командой, который должен быть закрыт первым.Существует уже открытый DataReader, связанный с этой командой, без вложенных datareaders

Я читал, что это может произойти, когда в одном соединении есть вложенные DataReaders, но в моем случае я использую следующий код для выполнения всех запросов.

private SqlTransaction Transaction { get; set; } 
    private SqlConnection Connection { get; set; } 
    private DbRow Row {get; set;} 

    public Row Exec(string sql){ 
     try{ 
      //Begin connection/transaction 
      Connection = new SqlConnection(connectionString); 
      Connection.Open(); 
      Transaction = Connection.BeginTransaction("SampleTransaction"); 

      //create command 
      SqlCommand command = new SqlCommand(sql, Connection); 
      command.Transaction = Transaction; 

      //execute reader and close it 
      //HERE IS THE PROBLEM, THE READER ALWAYS READ UNTIL THE END 
      //BEFORE ANOTHER CAN BE OPENED 
      reader = command.ExecuteReader();     
      while (reader.Read()) 
      { 
       object[] value = new object[reader.FieldCount]; 
       reader.GetValues(value); 
       List<object> values = new List<object>(value);      
       Rows.Add(values); 
      }     
      reader.Close(); 
      Transaction.Commit(); 
      Connection.Dispose(); 
      Connection = null; 
     } 
     catch 
     { 
      Transaction.Rollback(); 
      Connection.Dispose(); 
      Connection = null; 
     } 
     finally 
     { 
      if (reader != null && !reader.IsClosed) reader.Close(); 
     } 
    } 

Таким образом, результат сохраняется в объекте, и нет вложенных считывателей. Я также читал, что добавление в строку соединения «MultipleActiveResultSets = True» может решить проблему при использовании вложенных считывателей. Это решение также решает мою проблему? Поскольку ошибка является промежуточной и происходит только в рабочей среде, я не могу ее много раз проверять.

There is already an open DataReader associated with this Command which must be closed first. at 
      System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at 

System.Data.SqlClient.SqlInternalTransaction.Rollback() at 

System.Data.SqlClient.SqlTransaction.Rollback() at 

Application.Lib.DB.DBSQLServer.Rollback() 
at Application.Lib.DB.DBSQLServer.Execute(String sql, Dictionary`2 parameters, 

Nullable`1 timeout, Boolean useTransaction) at 

Application.UtilDB.Execute(String sql, Dictionary`2 parameters, Nullable`1 

timeout, Boolean useTransaction) in c:\Application\DBUtil.cs:line 37 at 

Application.A.CollectionFromDataBase(Int32 cenId, 

IDB db, Int32 includeId, Boolean allStatus) in c:\Application\Activities.cs:line 64 at 

Application.ActivitiesController.CheckForConflictsBeforeSave(String aulId, String insId) in c:\Application\AlocController.cs:line 212 
+0

Не могли бы вы вывести код для этого всего метода? –

+0

@BryanCrosby Я только что отредактировал вопрос, это не полный код, но это важная часть. – dinhokz

+0

Можете ли вы также опубликовать трассировку стека для исключения? –

ответ

2

Проблема заключалась в том, что при сбое запроса транзакция не может быть отброшена, поскольку считыватель данных уже открыт для обработки запроса.

Второе исключение выбрано, и первый из них потерян.

Я просто поместил откат внутри блока catch catch и использовал класс AggregateException, чтобы выбросить оба исключения.

try 
{ 
    Transaction.Rollback(); 
    Connection.Dispose(); 
    Connection = null; 
} 
catch (Exception ex2) 
{              
    throw new AggregateException(new List<Exception>() { e, ex2 }); 
} 

Хотя сделка будет откат в любом случае, я думаю, вы также можете попробовать, чтобы закрыть чтения данных до отката, так что вероятно, будет работать.

if (reader != null && !reader.IsClosed) 
    reader.Close(); 
Transaction.Rollback(); 
1

Поскольку это происходит только при производстве, более вероятно, что ошибка находится вне кода, который вы подключили.

Наиболее распространенный способ предотвратить это всегда код в следующем виде:

reader = command.ExecuteReader(); 
try 
{ 
     for (int i = 0; i < reader.FieldCount; i++) 
     { 
      dbResult.Columns.Add(reader.GetName(i)); 
      dbResult.Types.Add(reader.GetDataTypeName(i)); 
     } 
     while (reader.Read()) 
     { 
      object[] value = new object[reader.FieldCount]; 
      reader.GetValues(value); 
      List<object> values = new List<object>(value);      
      Rows.Add(values); 
     }        
} 
finally 
{ 
    reader.Close(); 
} 

Обратите внимание на finally блок, он делает, что читатель не будет закрыто ни на что. У меня создается впечатление, что что-то происходит в вашем коде, что оставляет читателя открытым, но ошибка не отображается в коде, который вы опубликовали.

Я рекомендую вам заключить его в вышеуказанный блок try/finally , и ваша ошибка, скорее всего, будет решена..

Редактировать, чтобы уточнить: это может не разрешить любую ошибку, находящуюся вне области первоначально показанного кода, но это предотвратит открытие чтения данных. Блок finally, который я предложил, не будет блокировать какие-либо исключения, они будут распространяться на любого обработчика, который вы используете за его пределами.

+0

Конечно, зная, что ошибка существует и остается без исправления, на самом деле не является решением. – Steve

+0

Как я и предположил, ваша ошибка выглядит ** вне исходного кода, видимого нам **. Например, мы не можем видеть, где объявляется 'command' или' reader', и как он используется вне рамки кода, который вы нам показали. – bokibeg

+0

Попытайтесь понять мою точку зрения.Добавление предложения finally решит проблему с читателем. Он закроет читателя независимо от того, что, как вы говорите. И это то, что я считаю неприемлемым в вашем ответе. Если плакат следует вашим советам, чтобы вслепую добавить предложение finally, он/она забудет, что есть проблема, и, вероятно, он будет разворачивать прослушиваемый код, который в любой момент поднимет голову. На этом этапе лучше добавить catch и зарегистрировать исключение где-нибудь или просто отобразить его. – Steve

Смежные вопросы

 Смежные вопросы