.NET:SqlDataReader.Close或.Dispose结果在Timeout Expired异常中

当试图在SqlDataReader上调用Close或Dispose时,我得到一个超时过期异常。 如果你有一个到SQL Server的DbConnection,你可以用下面的方法自己重新创建它:

String CRLF = "rn";
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:

  • ErrorCode:-2146232060(0x80131904)
  • 消息:“超时已过期,操作完成之前已超时或服务器没有响应。”

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


    Cruizer有答案:call 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);
    }
    
    链接地址: http://www.djcxy.com/p/56675.html

    上一篇: .NET: SqlDataReader.Close or .Dispose results in Timeout Expired exception

    下一篇: Multiple Simultaneous SQL Connection Timeouts In Multithreaded Windows Service