NET: SqlDataReader.Close ou .Dispose resultados em tempo limite excepção Expirado
-
02-07-2019 - |
Pergunta
Ao tentar chamar Close ou Dispose em um SqlDataReader i obter um limite expirou exceção. Se você tem um DbConnection para SQL Server, você pode reproduzi-lo-se com:
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();
Se você chamar reader.Close () ou reader.Dispose () que vai lançar um System.Data.SqlClient.SqlException:
- ErrorCode: -2146232060 (0x80131904)
- Mensagem: "Tempo limite expirou O tempo limite esgotou antes da conclusão da operação ou o servidor não está respondendo.".
Solução
é porque você acabou de abrir o leitor de dados e não têm completamente iterado ainda. você precisará .Cancel () o objeto DbCommand antes de tentar fechar um leitor de dados que ainda não foi concluída (e o DbConnection também). é claro, por .Cancel () - ing seu DbCommand, eu não tenho certeza disso, mas você pode encontrar alguma outra exceção. mas você deve apenas pegá-lo se isso acontecer.
Outras dicas
Cruizer tinha a resposta: chamada command.Cancel ():
using (DbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
using (DbDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
{
cmd.Cancel();
break;
}
}
}
}
Também é útil saber que você pode chamar o Anular mesmo se o leitor já leu todas as linhas (ou seja, ele não jogar um pouco de "nada para cancelar" exceção.)
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();
}
Onde você realmente ler os dados? Você está apenas criando um leitor, mas não a leitura de dados. É apenas um palpite, mas talvez o leitor tem problemas para fechar, se você não está lendo;)
DbDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
int index = rdr.GetInt32(0);
}