.NET: SqlDataReader.Close или .Dispose приводит к исключению Timeout Expired - PullRequest
5 голосов
/ 25 сентября 2008

При попытке вызвать 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)
  • Сообщение: «Время ожидания истекло. Время ожидания истекло до завершения операции или сервер не отвечает».

Ответы [ 3 ]

13 голосов
/ 25 сентября 2008

это потому, что вы только что открыли считыватель данных и еще не полностью просмотрели его. вам нужно будет .Cancel () ваш объект DbCommand, прежде чем пытаться закрыть читатель данных, который еще не завершен (и DbConnection также). конечно, с помощью .Cancel () - используя вашу DbCommand, я не уверен в этом, но вы можете столкнуться с некоторым другим исключением. но вы должны просто поймать это, если это произойдет.

2 голосов
/ 25 сентября 2008

Крейсер получил ответ: вызов команды. Отмена ():

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

Также полезно знать, что вы можете вызвать Отмена, даже если читатель уже прочитал все строки (т. Е. Он не выдает «ничего не отменять» исключение.)

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();
}
0 голосов
/ 25 сентября 2008

Где вы на самом деле читаете данные? Вы просто создаете читателя, но не читаете данные. Это всего лишь предположение, но, возможно, у читателя проблемы с закрытием, если вы не читаете;)

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