SQL Server 2005 超时与 .NET 适配器

本文关键字:NET 适配器 超时 Server 2005 SQL | 更新日期: 2023-09-27 17:56:58

我正在运行一个从 C# TableAdapter 返回 ~30,000 行的查询,并且经常出现如下错误:

Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding. 
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)'r'n   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)'r'n   at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)

如果我运行相同的查询,返回的行较少,则不会收到错误。如果我自己运行与 C# 中的 TableAdapter 在 SSMS 中运行的完全相同的查询,则 30,000 行的查询返回正常。

什么原因可能导致这种情况?

编辑:SSMS 中的查询需要 ~7 秒

SQL Server 2005 超时与 .NET 适配器

应延长查询的超时期限以获取结果。由于结果集很大,查询可能需要一些时间才能完成。最有可能的是,在生成结果之前,超时期限即将到期

可以使用 SQLCommand 的 CommandTimeout 属性来设置过期时间。将其设置为较长时间以进行测试,并检查是否获得结果

这可能是索引的问题。 特别是因为你说查询在 SSMS 中运行,但不在代码中运行。 请参阅这篇文章,其中包含更多信息(并且是IMO的好读):

http://www.sommarskog.se/query-plan-mysteries.html

查询需要多长时间? 拿 SQL 直接在数据库中运行它,它有多快? 如果需要很长时间,可能需要使用索引或其他调谐方法进行翻转。

您可以增加超时,但为什么要返回 30,000 条记录。 如果这不是后台进程,则应将查询设置为分页以一次返回 X 条记录。

如果您绝对需要 30,000 条记录:

用户使用DataReader,它比数据适配器更快,资源密集更少,请记住它使用仅向前(消防)方法来进行数据检索。

一次以块的形式拉取记录,例如拉取 1000、处理、

拉取 1000、处理...

在 .Net 中超时调整查询以使其运行得更快

如果数据不太不稳定,则考虑缓存 30,000 条记录

这是推测性的,但您可能会遇到导致问题的参数嗅探实例。

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

快速解决方法是添加局部变量,将参数值复制到局部变量,然后在查询中使用局部变量。从上面的文章

CREATE PROCEDURE MyProcedure
     @UserName nvarchar(20)
 AS
 BEGIN
     DECLARE @myUserName nvarchar(20)
     SET @myUserName = @UserName
     -- Insert statements for procedure here
     SELECT DisplayName, FirstName, LastName 
     FROM dbo.User
     WHERE UserName = @myUserName
END

有关此处实际发生的情况的更多信息:http://www.sqlpointers.com/2006/11/parameter-sniffing-stored-procedures.html