.NET:SqlDataReader.Закрыть или .Dispose приводит к исключению с истекшим временем ожидания
-
02-07-2019 - |
Вопрос
При попытке вызвать Close или Dispose в SqlDataReader я получаю исключение с истекшим таймаутом.Если у вас есть DbConnection к SQL Server, вы можете воспроизвести его самостоятельно с помощью:
String CRLF = "\r\n";
String sql =
"SELECT * " + CRLF +
"FROM (" + CRLF +
" SELECT (a.Number * 256) + b.Number AS Number" + CRLF +
" FROM master..spt_values a," + CRLF +
" master..spt_values b" + CRLF +
" WHERE a.Type = 'p'" + CRLF +
" AND b.Type = 'p') Numbers1" + CRLF +
" FULL OUTER JOIN (" + CRLF +
" SELECT (print("code sample");a.Number * 256) + b.Number AS Number" + CRLF +
" FROM master..spt_values a," + CRLF +
" master..spt_values b" + CRLF +
" WHERE a.Type = 'p'" + CRLF +
" AND b.Type = 'p') Numbers2" + CRLF +
" ON 1=1";
DbCommand cmd = connection.CreateCommand();
cmd.CommandText = sql;
DbDataReader rdr = cmd.ExecuteReader();
rdr.Close();
Если вы вызовете reader.Close() или reader.Dispose(), это вызовет исключение System.Data.SqlClient.SQLException:
- Код ошибки:-2146232060 (0x80131904)
- Сообщение:"Тайм-аут истек.Период ожидания, прошедший до завершения операции, или сервер не отвечает ".
Решение
это потому, что вы только что открыли программу чтения данных и еще не полностью выполнили итерацию по ней.вам нужно будет .Cancel() ваш объект DbCommand перед попыткой закрыть программу чтения данных, которая еще не завершена (а также DbConnection).конечно, с помощью .Cancel()-вашей DbCommand, я не уверен в этом, но вы можете столкнуться с каким-то другим исключением.но вы должны просто поймать это, если это произойдет.
Другие советы
У Крузера был ответ:вызов команды.Отмена ():
using (DbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
using (DbDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
{
cmd.Cancel();
break;
}
}
}
}
Также полезно знать, что вы можете вызвать Cancel , даже если программа чтения уже прочитала все строки (т. е.это не выбрасывает каких-то "нечего отменять" исключение.)
DbCommand cmd = connection.CreateCommand();
try
{
cmd.CommandText = sql;
DbDataReader rdr = cmd.ExecuteReader();
try
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
break;
}
cmd.Cancel();
}
finally
{
rdr.Dispose();
}
}
finally
{
cmd.Dispose();
}
Где вы на самом деле считываете данные?Вы просто создаете средство чтения, но не считываете Данные.Это всего лишь предположение, но, возможно, у читателя есть проблемы с закрытием, если вы не читаете ;)
DbDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
int index = rdr.GetInt32(0);
}