2015-10-13 2 views
0

У меня есть код, который периодически запускает запрос к базе данных SQL Server и сохраняет строки в словаре. Этот код работает нормально в нашей производственной среде около 3 лет. Совсем недавно он рушился с необработанным исключением. Для устранения неполадок я удалил все, кроме чтения столбца, и завернул все в try-catch. Вот исключение:Исключение таймаута SqlDataReader

Первый шанс исключение типа «System.Data.SqlClient.SqlException» произошло в System.Data.dll Время ожидания истекло. Период ожидания истекает до завершения операции или сервер не отвечает.

 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) 
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 
    at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len) 
    at System.Data.SqlClient.TdsParser.SkipValue(SqlMetaDataPriv md, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.TdsParser.SkipRow(_SqlMetaDataSet columns, Int32 startCol, TdsParserStateObject stateObj) 
    at System.Data.SqlClient.SqlDataReader.CleanPartialRead() 
    at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout) 

Я использую что-то очень похожее на:

// query is a simple select from 1 table, not long running by any means 
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock)"; //connection timeout 
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock) order by col1, col2"; //connection does not time out 

SqlCommand command = new SqlCommand(query,connection) 
SqlDataReader reader = command.ExecuteReader(); 

while (!reader.IsClosed && reader.Read()) { 
    try { 
    string test0 = reader[0].ToString(); 
    string test1 = reader[1].ToString(); 
    string test2 = reader[2].ToString(); 
    string test3 = reader[3].ToString(); 
    // here is where I would normally processes and store into dictionary 
    } 
    catch (Exception e){ 
    //make some noises 
    } 
} 

При запуске запроса с другими методами, он возвращает практически мгновенно (а под второй), но только чтобы увидеть, что произойдет, я увеличил CommandTimeout до 60 секунд (по умолчанию 30), что только увеличило время, в течение которого моя программа зависала, прежде чем выбрасывать исключение.

По предложению @ frisbee я добавил запрос к предложению, который останавливает соединение с тайм-аутом.

Я думаю, что одна из операций Read() не возвращается, а затем вызывает соединение с таймаутом, но я понятия не имею, что может вызвать это. Обычно это происходит в определенной строке при чтении столбца 3, но не всегда. Запрос возвращает чуть менее 50 тыс. Строк, и иногда он будет проходить через все, а иногда только через 15 тыс.

+0

Если вы подозреваете, что доступ к столбцам является виновником, удалите его (для устранения целей ...). агрегировать 'reader.FieldCount' в' int' внутри вашего цикла и ничего не делать (это просто так, чтобы вы «касались» каждой строки каким-то образом). см., если вы все еще получаете свои тайм-ауты. – Amit

+0

Тот же результат, за исключением того, что он выдает исключение в Read() – Pete

+0

, поэтому теперь вы знаете, что это не столбцы (вряд ли начинались). Я был бы очень удивлен, если это действительно не проблема с БД. Что изменилось с 3 лет назад? больше данных? – Amit

ответ

0

Почему бы вам не пойти и установить свойство CommandTimeout вашего экземпляра SqlCommand на большое число? Это заставит ваш код работать.

На другом конце вам нужно отлаживать все, что заставляет сервер так долго заканчивать свою работу. Вы ничего не можете сделать с той стороны .NET. Вам нужно будет выполнить базовый код, который выполняется на SQL Server.

+0

Я установил его на 60 секунд. Но, как я уже сказал, сервер не принимает такой взгляд, чтобы вернуть результат. Если я запустил запрос в студии управления sql, запрос вернется довольно близко к мгновенному. Я думаю, что его тайм-аут на последующих операциях Read(), когда выполняется итерация по набору результатов, вызывающая проблему. – Pete

+0

@pete Последующее чтение по-прежнему является таймаутом. – Paparazzi

+0

@Frisbee Он должен иметь возможность косить эти строки менее чем за секунду, не говоря уже о 30 или 60. Я * * * установил мой тайм-аут выше, чтобы увидеть, есть ли какой-либо эффект, все еще бросая исключение. – Pete

0

Каждый другой запуск? Возможно, вы используете команду?
Если вы используете MARS и совместное соединение - не

using (SqlCommand cmd = con.CreateCommand) 
{ 
    using (SqlDataReader rdr = cmd.ExecuteReader()) 
    { 
    } 
} 
0

Почему вы проверяете, если читатель закрыт на ваше время цикла?

Попробуйте использовать using, чтобы обеспечить правильную работу. Следующее должно сделать все плавно для вас.

using (SqlConnection connection = MyDBConnection) 
{ 
    connection.Open(); 
    SqlCommand command = new SqlCommand("SQL Query Here", connection) { CommandTimeout = 0 }; 


    using (var reader = command.ExecuteReader()) 
    { 
     try 
     { 
      while (reader.Read()) 
      { 

       string test0 = reader[0].ToString(); 
       string test1 = reader[1].ToString(); 
       string test2 = reader[2].ToString(); 
       string test3 = reader[3].ToString(); 

      } 

     } 
     catch (Exception e) 
     { 

      //Make some Noise 

     } 
    } 
} 
+0

Я проверял, закрыт ли читатель, потому что, поймав первое исключение, он зациклился и прочитал из закрытого читателя ... и исключил другое исключение. С тех пор я изменил код, чтобы обернуть весь цикл while в блок try/catch. – Pete

+0

Установка таймаута команды на 0 позволит бесконечно оставаться открытым, попробуйте. Если вы подозреваете, что блокировки таблиц используют WITH (NOLOCK) для каждой таблицы, которую вы вводите. –

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