使用ADO.Net的查询的连接超时异常

时间:2008-09-19 21:08:46

标签: c# .net ado.net timeout

更新:看起来查询不会抛出任何超时。连接超时。

这是用于执行查询的示例代码。有时,在执行耗时的查询时,会抛出超时异常。

无法使用以下任何技术: 1)增加超时。 2)使用回调异步运行它。这需要以同步方式运行。

请执行任何其他技术以在执行耗时的查询时保持连接活动?

private static void CreateCommand(string queryString,
    string connectionString)
{
    using (SqlConnection connection = new SqlConnection(
               connectionString))
    {
        SqlCommand command = new SqlCommand(queryString, connection);
        command.Connection.Open();
        command.ExecuteNonQuery();
    }
}

16 个答案:

答案 0 :(得分:16)

由于您使用的ExecuteNonQuery不返回任何行,因此您可以尝试这种基于轮询的方法。它以asyc方式执行查询(没有回调) 但应用程序将等待(在while循环内),直到查询完成。来自MSDN。这应该解决超时问题。请试一试。

但是,我同意其他人的看法,你应该多考虑优化查询,以便在30秒内完成。

        IAsyncResult result = command.BeginExecuteNonQuery();

        int count = 0;
        while (!result.IsCompleted)
        {
            Console.WriteLine("Waiting ({0})", count++);
            System.Threading.Thread.Sleep(1000);
        }
        Console.WriteLine("Command complete. Affected {0} rows.",
        command.EndExecuteNonQuery(result));

答案 1 :(得分:4)

您应首先检查您的查询,看它是否已经过优化,并且不会以某种方式运行缺失的索引。 30秒为大多数查询分配,即使在大型数据库上进行了适当调整也是如此。如果您有使用查询计划的可靠证据,查询无法以更快的速度执行,那么您应该增加超时,没有其他方法来保持连接,这是超时终止连接的目的,如果查询未在该时间范围内完成。

答案 2 :(得分:1)

我必须同意Terrapin。

您可以选择如何缩短时间。首先,如果您的公司雇佣了DBA,我建议您向他们寻求建议。

如果这不是一个选项,或者如果你想先尝试一些其他的东西,这里有三个主要选择:

  1. 将查询分解为在超时下运行的组件。这可能是最简单的。
  2. 更改查询以优化通过数据库的访问路径(通常:尽可能密切地命中索引)
  3. 更改或添加索引以影响查询的访问路径。

答案 3 :(得分:1)

如果您受限于使用更改超时值的默认过程,您很可能需要做更多的工作。想到以下选项

  1. 使用您的DBA和其他代码审核验证您已尽可能优化查询
  2. 处理底层数据库结构,看看是否可以在数据库端获得任何增益,创建/修改idex。
  3. 将它分成多个部分,即使这意味着运行具有多个返回参数的过程,这些参数只是调用另一个参数。 (这个选项并不优雅,老实说,如果你的代码真的花了这么多时间,我会去管理层并重新讨论30秒超时)

答案 4 :(得分:1)

我们最近在SQL Server 2000数据库上遇到了类似的问题。

在查询期间,在数据库服务器上的主数据库上运行此查询,并查看是否存在应该进行故障排除的锁定:

select 
  spid,
  db_name(sp.dbid) as DBname,
  blocked as BlockedBy,
  waittime as WaitInMs,
  lastwaittype,
  waitresource,
  cpu,
  physical_io,
  memusage,
  loginame,
  login_time,
  last_batch,
  hostname,
  sql_handle
from sysprocesses sp
where (waittype > 0 and spid > 49) or spid in (select blocked from sysprocesses where blocked > 0)

SQL Server Management Studio 2008还包含一个非常酷的活动监视器,可让您在查询期间查看数据库的运行状况。

在我们的例子中,它是一个使网络繁忙的网络锁。这是一些遗留的VB代码,它没有足够快地断开其结果集。

答案 5 :(得分:1)

如果禁止使用数据访问API的功能来允许查询持续超过30秒,那么我们需要查看SQL。

与优化SQL的优势相比,优化ADO.NET使用所带来的性能提升很小。

您已经在使用最有效的SQL执行方法。其他技术会慢慢变慢(尽管如果你快速检索你的行并且使用DataSet的一些非常慢的客户端处理,你可能能够将初始检索缩短到不到30秒,但我对此表示怀疑。 )

如果我们知道您是否正在插入,那么也许您应该使用批量插入。但是我们不知道你的sql的内容。

答案 6 :(得分:1)

这是一个UGLY hack,但可能有助于临时解决您的问题,直到您可以解决实际问题

    private static void CreateCommand(string queryString,string connectionString)
    {
        int maxRetries = 3;
        int retries = 0;
        while(true)
        {
            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    SqlCommand command = new SqlCommand(queryString, connection);
                    command.Connection.Open();
                    command.ExecuteNonQuery();
                }
                break;
            }
            catch (SqlException se)
            {
                if (se.Message.IndexOf("Timeout", StringComparison.InvariantCultureIgnoreCase) == -1)
                    throw; //not a timeout

                if (retries >= maxRetries)
                    throw new Exception( String.Format("Timedout {0} Times", retries),se);

                //or break to throw no error

                retries++;
            }
        }
    }

答案 7 :(得分:0)

command.CommandTimeout *= 2;

这将使默认超时时间加倍,即30秒。

或者,将CommandTimeout的值放在配置文件中,这样您就可以根据需要进行调整而无需重新编译。

答案 8 :(得分:0)

如果你绝对无法增加超时,你唯一的选择就是减少查询在默认的30秒超时内执行的时间。

答案 9 :(得分:0)

您应该将查询分成多个块,每个块在超时期限内执行。

答案 10 :(得分:0)

我倾向于不喜欢增加连接/命令超时,因为在我看来这是一个处理症状的问题,而不是问题

答案 11 :(得分:0)

只需将sqlcommand的CommandTimeout属性设置为0,这将导致命令等待查询完成...     例如:

SqlCommand cmd = new SqlCommand(spName,conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;

答案 12 :(得分:0)

您是否考虑过将查询分解为几个较小的块?

此外,您是否在数据库引擎优化顾问中运行了查询:

Management Studio>工具>数据库引擎优化顾问

最后,我们可以看一下查询本身吗?

欢呼声

答案 13 :(得分:0)

您是否尝试将sql包装在存储过程中,它们似乎有更好的内存管理。在使用经典ADO进行内部查询的plan sql语句之前,已经看到过这样的超时。即select * from(select ....)t inner join somthingTable。内部查询返回大量结果的位置。

其他提示 1.使用with(nolock)执行提示执行读取,它很脏,我不推荐它,但它会更快。 2.还要查看您尝试运行的sql的执行计划,并减少行扫描,即连接表的顺序。 3.查看为表添加一些索引以便更快地读取。 4.我还发现删除行非常昂贵,您可以尝试限制每次调用的行数。 5.使用#temporary表交换@table变量在过去对我也有用。 6.您可能还保存了糟糕的执行计划(听到,从未见过)。

希望这有帮助

答案 14 :(得分:0)

  

更新:看起来查询没有   抛出任何超时。连接是   超时。

I.o.w。,即使您不执行查询,连接也会超时?因为有两个超时:连接和查询。每个人似乎都专注于查询,但是如果你得到连接超时,那就是网络问题并且与查询无关:显然,必须首先建立连接,然后才能运行查询。

答案 15 :(得分:0)

尝试将结果分页回来可能是值得的。