SqlDataReader挂起Dispose()

Qué*_*dre 5 .net c# sqldatareader

我使用以下方法对数据库执行查询并读取数据:

using(SqlConnection connection = new SqlConnection("Connection string"))
{
    connection.Open();

    using(SqlCommand command = new SqlCommand("SELECT * FROM TableName", connection))
    {
        using (SqlDataReader reader = command.ExecuteReader())
        {
              // read and process data somehow (possible source of exceptions)
        } // <- reader hangs here if exception occurs
    } 
}
Run Code Online (Sandbox Code Playgroud)

在读取和处理数据时,可能会发生一些异常.问题是当抛出异常时DataReader挂起Close()电话.你有什么想法吗??? 以及如何以正确的方式解决这个问题?当我在处理读卡器之前编写try..catch..finally块而不是using和调用时,问题就消失了.command.Cancel()finally

工作版本:

    using(SqlConnection connection = new SqlConnection("Connection string"))
    {
        connection.Open();

        using(SqlCommand command = new SqlCommand("SELECT * FROM TableName", connection))
        {
            SqlDataReader reader = command.ExecuteReader();
            try
            {
                // read and process data somehow (possible source of exceptions)
            }
            catch(Exception ex)
            {
                // handle exception somehow
            }
            finally
            {
               command.Cancel(); // !!!
               reader.Dispose();
            }
        } 
    }
Run Code Online (Sandbox Code Playgroud)

usr*_*usr 6

发生异常时,在收到所有数据之前停止处理数据.如果您在几行后中止处理,即使没有例外,您也可以重现此问题.

处理命令或阅读器时,查询仍在服务器上运行.ADO.NET只是像疯了一样读取所有剩余的行和结果集并抛弃它们.这样做是因为服务器正在发送它们,协议需要接收它们.

调用SqlCommand.Cancel向SQL Server发送"注意",导致查询真正中止.与在SSMS中按取消按钮相同.

总而言之,每当您停止处理行时会发生此问题,尽管有更多行是入站的.您的解决方法(调用SqlCommand.Cancel)是正确的解决方案.