【问题标题】:.NET: SqlDataReader.Close or .Dispose results in Timeout Expired exception.NET:SqlDataReader.Close 或 .Dispose 导致 Timeout Expired 异常
【发布时间】:2010-09-13 02:23:35
【问题描述】:

当尝试在 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)
  • 消息:“超时已过。在操作完成之前超时时间已过或服务器没有响应。”

【问题讨论】:

    标签: .net sql-server database timeout


    【解决方案1】:

    这是因为您刚刚打开数据阅读器,还没有完全迭代它。在尝试关闭尚未完成的数据读取器(以及 DbConnection)之前,您需要 .Cancel() 您的 DbCommand 对象。当然,通过 .Cancel()-ing 您的 DbCommand,我不确定这一点,但您可能会遇到其他一些异常。但如果它发生,你应该抓住它。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 读取零行、一行或多行时会出现问题。
      【解决方案3】:

      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 也很有帮助(即它不会抛出一些 “nothing to 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();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-10
        • 2013-05-30
        • 1970-01-01
        • 2013-12-21
        • 2011-02-17
        • 1970-01-01
        相关资源
        最近更新 更多