我在 Stackoverflow 上问了下面的问题,但没有得到任何答案,但是有人建议我也在 serverfault 上问这个问题。希望有人能帮忙。
我最近将我的 ASP.Net MVC 3 Web 应用程序(Entity Framework 4.1 用于数据持久性)发布到实时服务器。该应用程序位于一台 Web 服务器上,数据库(SQL Server 2008)位于另一台单独的服务器上。
该网站仅上线几天,点击量很少,因此数据库表中包含的记录很少(最多 10-20 条)。
我还在网站中集成了 ELMAH(ASP.NET 的错误日志模块和处理程序),并且已经收到了以下错误的几个实例
System.Data.SqlClient.SqlException:超时已过期。操作完成前已超时或服务器未响应。
以下是 ELMAH 提供的完整详细信息
System.Data.EntityException:基础提供程序打开失败。 ---> System.Data.SqlClient.SqlException:超时已过期。操作完成前已超过超时期限,或者服务器未响应。在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔 breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj,UInt32 错误) 在 System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult,TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() 在 System.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(布尔加密,布尔 trustServerCert,布尔& marsCapable) 在 System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo,SqlInternalConnectionTds connHandler, System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo、String newPassword、Boolean ignoreSniOpenTimeout、TimeoutTimer timeout、SqlConnection owningObject)处的布尔 ignoreSniOpenTimeout、Int64 timerExpire、Boolean encrypt、Boolean trustServerCert、Boolean IntegratedSecurity)位于 System.Data.SqlClient.SqlInternalConnectionTds.LoginWithFailover(布尔 useFailoverHost、ServerInfo primaryServerInfo、String failoverHost、String newPassword、Boolean redirectedUserInstance、SqlConnection owningObject、SqlConnectionString connectionOptions、TimeoutTimer timeout)位于 System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject、TimeoutTimer timeout、SqlConnectionString connectionOptions、String newPassword,布尔重定向用户实例)在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity 身份,SqlConnectionString connectionOptions,对象提供程序信息,字符串 newPassword,SqlConnection owningObject,布尔重定向用户实例)在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions 选项,对象 poolGroupProviderInfo,DbConnectionPool 池,DbConnection owningConnection)在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection,DbConnectionPool 池,DbConnectionOptions 选项)在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)在System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 在 System.Data.SqlClient.SqlConnection.Open() 在 System.Data.EntityClient.EntityConnection。OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) --- 内部异常堆栈跟踪结束 --- 在 System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) 在 System.Data.EntityClient.EntityConnection.Open() 在 System.Data.Objects.ObjectContext.EnsureConnection() 在 System.Data.Objects.ObjectQuery
1.GetResults(Nullable
1 forMergeOption) 在 System.Data.Objects.ObjectQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Collections.Generic.List
1..ctor(IEnumerable 1 源) System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary 2 参数) 在 System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.b__12() 在 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func 1 filters, ActionDescriptor actionDescriptor, IDictionary`2 参数) 在 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
1 continuation) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
发生此错误的情况是由于 SELECT 查询。这些选择查询非常简单,即
从表中选择 col1、col2、col3,其中 col1 = 1
正如我所说,数据库中的数据非常少,因此查询并不会拉回数百条记录。
我已经对此进行了一些研究,使用了互联网和堆栈溢出有人建议增加dbContext 命令超时财产,但是,我不明白为什么我需要这样做。是的,如果我要提取大量记录,但正如我所说,这些很简单选择最多可返回 1 至 5 条记录。
我还知道开发人员需要关注 Entity Framework 生成的 SQL,因此我下载并运行了这个试用版http://www.datawizard.com为了查看为导致问题的 Entity Framework SELECT 查询创建的 SQL。同样,分析器显示这些查询的语法非常简单,因此我认为这不是问题所在。
我开始想也许这与我的数据库和 Web 应用程序位于不同的服务器上有关,但是,我没有主意!
如果有人能帮助或建议我解决这个问题,我将不胜感激。
感谢大家。
答案1
为了消除客户端或网络问题,请在启用客户端统计功能的管理工作室中运行生成的 SQL,并观察执行查询所需的运行时间和工作量。
您可以在 SELECT 查询后面跟上 GO,连续执行任意次数,这样就可以获得有意义的样本集的平均值:
SELECT col1, col2, col3 FROM table WHERE something
GO 1000
还请考虑一下,由于这样的框架隐藏了许多(如果不是大多数的话)实际的 SQL,所以这可能不是实际的问题;也许它试图大规模并行化查询,或者由于涉及 ORM,它在表上持有硬(独占读写)锁。
答案2
从您提供的堆栈跟踪来看,这不是命令超时,而是连接超时(有这样一行:)System.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(...)
。这可能是 VS 2010 中的一个已知错误,如果您使用镜像,请参阅这篇博客文章了解更多信息。