SqlDataReader超时异常

时间:2015-10-13 19:57:11

标签: c# .net sql-server

我有一些代码会定期对SQL Server数据库运行查询并将行存储在字典中。此代码在我们的生产环境中运行良好约3年。就在最近,它已经因未处理的异常而崩溃。出于疑难解答的目的,除了列读取之外,我删除了所有内容,并将所有内容包装在try-catch中。这是一个例外:

  

System.Data.dll中发生了'System.Data.SqlClient.SqlException'类型的第一次机会异常   超时已过期。操作完成之前经过的超时时间或服务器没有响应。

   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
   at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
   at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len)
   at System.Data.SqlClient.TdsParser.SkipValue(SqlMetaDataPriv md, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.SkipRow(_SqlMetaDataSet columns, Int32 startCol, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.CleanPartialRead()
   at System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout)

我使用的东西非常相似:

// query is a simple select from 1 table, not long running by any means
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock)"; //connection timeout
string query = "SELECT col1, col2, col3, col4 FROM db.dbo.tbl_name WITH (nolock) order by col1, col2"; //connection does not time out

SqlCommand command = new SqlCommand(query,connection)
SqlDataReader reader = command.ExecuteReader();

while (!reader.IsClosed && reader.Read()) {
  try {
    string test0 = reader[0].ToString();
    string test1 = reader[1].ToString();
    string test2 = reader[2].ToString();
    string test3 = reader[3].ToString();
    // here is where I would normally processes and store into dictionary
  }
  catch (Exception e){
    //make some noises
  }
}

当我使用其他方法运行查询时,它几乎立即返回(远低于一秒),但只是为了看看会发生什么,我将CommandTimeout增加到60秒(从默认值30),只是增加了我的程序在抛出异常之前挂起的时间。

在@ frisbee的建议下,我在查询中添加了一个order by子句,它可以阻止连接超时。

我认为发生的事情是其中一个Read()操作没有返回,然后导致连接超时,但我不知道是什么原因造成的。这通常发生在读取第3列时的某一行,但并非总是如此。查询返回的行数不到5万,有时它会通过所有行,有时只通过15k

3 个答案:

答案 0 :(得分:0)

为什么不继续将SqlCommand实例的CommandTimeout属性设置为高数?这将使您的代码正常工作。

另一方面,您需要调试服务器这么长时间才能完成其工作。你不能从.NET方面做任何事情。您必须单步执行在SQL Server上执行的基础代码。

答案 1 :(得分:0)

每隔一次跑吗?你可能会分享一个命令吗? 如果您使用MARS并共享连接 - 请不要

using (SqlCommand cmd = con.CreateCommand) 
{   
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
    }
}

答案 2 :(得分:0)

为什么要检查阅读器是否在while循环中关闭?

尝试使用using确保正确处理问题。以下内容应该让一切顺利进行。

using (SqlConnection connection = MyDBConnection)
{
    connection.Open();
    SqlCommand command = new SqlCommand("SQL Query Here", connection) { CommandTimeout = 0 };


    using (var reader = command.ExecuteReader())
    {
        try
        {
            while (reader.Read())
            {

                string test0 = reader[0].ToString();
                string test1 = reader[1].ToString();
                string test2 = reader[2].ToString();
                string test3 = reader[3].ToString();

            }

        }
        catch (Exception e)
        {

            //Make some Noise

        }
    }
}