2008-09-25 4 views
5

Beim Versuch, Close oder Dispose auf einem SqlDataReader aufrufen, erhalte ich eine Timeout abgelaufen Ausnahme. Wenn Sie eine DbConnection zu SQL Server haben, können Sie es reproduzieren, sich mit:.NET: SqlDataReader.Close oder .Dispose Ergebnisse in Timeout Expired Ausnahme

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(); 

Wenn Sie reader.Close() aufrufen oder reader.Dispose() eine System.Data.SqlClient.SqlException werfen:

  • ErrorCode-: -2146232060 (0x80131904)
  • Nachricht: "Timeout abgelaufen die Timeout-Periode zur Beendigung des Betriebes vor verstrichen oder der Server antwortet nicht.."

Antwort

13

es ist, weil Sie gerade den Datenleser geöffnet haben und es noch nicht vollständig durchlaufen haben. Sie müssen .Cancel() Ihr DbCommand-Objekt, bevor Sie versuchen, einen Datenleser zu schließen, der noch nicht abgeschlossen ist (und auch die DbConnection). Natürlich bin ich bei .Cancel() - Ihrem DbCommand nicht sicher, aber Sie könnten auf eine andere Ausnahme stoßen. aber du solltest es einfach fangen, wenn es passiert.

0

Wo lesen Sie eigentlich die Daten? Sie erstellen gerade einen Leser, lesen aber keine Daten. Es ist nur eine Vermutung, aber vielleicht der Leser hat Probleme zu schließen, wenn Sie nicht lesen;)

DbDataReader rdr = cmd.ExecuteReader(); 
while(rdr.Read()) 
{ 
    int index = rdr.GetInt32(0); 
} 
+0

Problem geschieht, wenn Sie Null gelesen Zeilen, eine Zeile oder viele Zeilen. –

2

Cruizer hatte die Antwort: call command.Cancel():

using (DbCommand cmd = connection.CreateCommand()) 
{ 
    cmd.CommandText = sql; 
    using (DbDataReader rdr = cmd.ExecuteReader()) 
    { 
     while (rdr.Read()) 
     { 
      if (WeShouldCancelTheOperation()) 
      { 
      cmd.Cancel(); 
      break; 
      } 
     } 
    }  
} 

Es ist auch hilfreich zu wissen, dass Sie sogar Abbrechen anrufen können, wenn der Leser bereits alle Zeilen gelesen hat

(dh es ist nicht etwas „nichts zu annullieren“ Ausnahme wirft.)
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(); 
}