Dot-Net

.NET:SqlDataReader.Close 或 .Dispose 導致 Timeout Expired 異常

  • September 25, 2008

當試圖在 SqlDataReader 上呼叫 Close 或 Dispose 時,我得到一個超時過期異常。如果你有一個到 SQL Server 的 DbConnection,你可以自己複製它:

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)
  • 消息:“超時。在操作完成之前超時時間已過,或者伺服器沒有響應。”

這是因為您剛剛打開數據閱讀器,還沒有完全迭代它。在嘗試關閉尚未完成的數據讀取器(以及 DbConnection)之前,您需要 .Cancel() 您的 DbCommand 對象。當然,通過 .Cancel()-ing 您的 DbCommand,我不確定這一點,但您可能會遇到其他一些異常。但如果它發生,你應該抓住它。

Cruizer 得到了答案:呼叫 command.Cancel():

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

引用自:https://stackoverflow.com/questions/133374