.NET: SqlDataReader.Close o .Dispose genera un'eccezione scaduta timeout
-
02-07-2019 - |
Domanda
Quando provo a chiamare Close o Dispose su un SqlDataReader ottengo un'eccezione scaduta di timeout. Se hai un DbConnection su SQL Server, puoi riprodurlo tu stesso con:
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 chiami reader.Close () o reader.Dispose () genererà un System.Data.SqlClient.SqlException:
- ErrorCode: -2146232060 (0x80131904)
- Messaggio: " Timeout scaduto. Il periodo di timeout trascorso prima del completamento dell'operazione o il server non risponde. & Quot;
Soluzione
è perché hai appena aperto il lettore di dati e non lo hai ancora completamente ripetuto. dovrai .Cancel () il tuo oggetto DbCommand prima di tentare di chiudere un lettore di dati che non è stato ancora completato (e anche DbConnection). ovviamente, da .Cancel () - nel tuo DbCommand, non ne sono sicuro, ma potresti riscontrare qualche altra eccezione. ma dovresti prenderlo solo se succede.
Altri suggerimenti
Cruizer ha avuto la risposta: chiama command.Cancel ():
using (DbCommand cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
using (DbDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (WeShouldCancelTheOperation())
{
cmd.Cancel();
break;
}
}
}
}
È anche utile sapere che è possibile chiamare Annulla anche se il lettore ha già letto tutte le righe (ovvero non genera alcuna " nulla per annullare " ).
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();
}
Dove leggi effettivamente i dati? Stai solo creando un lettore, ma non stai leggendo i dati. È solo un'ipotesi, ma forse il lettore ha problemi a chiudere se non stai leggendo;)
DbDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
int index = rdr.GetInt32(0);
}