实体框架4存储过程调用时间输出

时间:2013-04-02 19:03:31

标签: .net entity-framework sql-server-2008-r2

我有一个导入EF4的存储过程,当我在30秒后用某些参数调用它时会抛出超时错误。在SQL Server探查器中,我可以看到存储过程调用使用适当的参数只需要超过30秒,这是我的应用程序的超时。

然而,当我执行在查询分析器中发送到探查器的相同SQL时,它会执行亚秒级。什么可能导致从EF调用和从SQL Server Management Studio调用之间的差异?

以下是.NET错误的完整堆栈跟踪。

  

[SqlException(0x80131904):超时已过期。超时期限   在完成操作之前经过或服务器没有经过   响应。]
  System.Data.SqlClient.SqlConnection.OnError(SqlException异常,   Boolean breakConnection)+2073486
  System.Data.SqlClient.SqlInternalConnection.OnError(SQLEXCEPTION   exception,Boolean breakConnection)+5064444
  System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()+234
  System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,   SqlCommand cmdHandler,SqlDataReader dataStream,   BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject   stateObj)+2275
  System.Data.SqlClient.SqlDataReader.ConsumeMetaData()+33
  System.Data.SqlClient.SqlDataReader.get_MetaData()+86
  System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,   RunBehavior runBehavior,String resetOptionsString)+311
  System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,Boolean   async)+987
  System.Data.SqlClient.SqlCommand.RunExecuteReader(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String   方法,DbAsyncResult结果)+162
  System.Data.SqlClient.SqlCommand.RunExecuteReader(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String   方法)+32
  System.Data.SqlClient.SqlCommand.ExecuteReader(的CommandBehavior   行为,字符串方法)+141
  System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(的CommandBehavior   行为)+12
  System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)   +10 System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand)   entityCommand,CommandBehavior行为)+443

     

[EntityCommandExecutionException:执行时发生错误   命令定义。有关详细信息,请参阅内部异常。]
  System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand   entityCommand,CommandBehavior行为)+479
  System.Data.Objects.ObjectContext.CreateFunctionObjectResult(EntityCommand   entityCommand,EntitySet entitySet,EdmType edmType,MergeOption   mergeOption)+182
  System.Data.Objects.ObjectContext.ExecuteFunction(String functionName,   MergeOption mergeOption,ObjectParameter [] parameters)+218
  System.Data.Objects.ObjectContext.ExecuteFunction(String functionName,   ObjectParameter []参数)+53
  MetaView.DAL.MFCMData.MFCMDATAEntities.GetTradingOpenPositionCounterParty(Nullable 1 positionDT, Nullable 1 tradingAccountID)in   C:\项目\ CASH \网络\ MetaView \ MetaView.DAL.MFCMData \ MFCMData.Designer.cs:7064   MetaView.BusinessLayer.Shared.Accounts.CounterParties.GetCounterParties(的Int32   tradingAccountID)in   C:\项目\ CASH \网络\ MetaView \ MetaView.BusinessLayer \共享\帐户\ CounterParties.cs:161

1 个答案:

答案 0 :(得分:24)

所以几个星期前我遇到了类似的问题,这是我们的一位DBA向我解释的(当然是转述和愚蠢):

当调用SQL Server存储过程时,服务器会为每个存储过程 per object_id 创建并缓存执行计划。有时,SQL Server可以创建一个错误的执行计划,具体取决于传入的参数值(在我们的例子中,对于可为空的参数,它是null)。发生这种情况时,快速解决方法是在SQL Server Management Studio(或您可能使用的任何数据库管理工具)中运行sp_recompile 'Schema.Procedure'。所有这一切都清楚了该存储过程的计划缓存。如果proc的下一个被调用者再次传入“bad”参数值,那么你将陷入相同的情况所以真正的解决方法是使用OPTIMIZE FOR为查询提供一个提示语法(参见http://msdn.microsoft.com/en-gb/library/ms181714.aspx)。

简而言之,如果您在OPTION (OPTIMIZE FOR (@myParameter = 'Some value that gives you a GOOD execution plan'))和/或WHERE条款之后添加ORDER BY,则应该解决问题。

此外,如果您想知道为什么在SSMS中执行相同的 SQL时,您总能获得快速的结果,因为SSMS对于名为ARITHABORT的选项(SET ARITHABORT ON的默认设置为ON )所有其他应用程序默认设置为关闭,但它是如何工作的,其含义超出了我的经验,我没有费心去阅读它。有人告诉我,我不应该使用它。我确信真正的DBA可以更好地解释原因。