当尝试在 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,我不确定这一点,但你可能会遇到一些其他异常。但如果它发生了,你应该抓住它。

其他提示

克鲁泽给出了答案:调用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();
}

您实际上在哪里读取数据?您只是创建一个阅读器,而不是读取数据。这只是一个猜测,但如果您不阅读,读者可能会遇到问题要关闭;)

DbDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
    int index = rdr.GetInt32(0);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top