我有一个使用LinqToSQL调用的存储过程。我没有做任何特别的事情,例如
MyDataContext db = new MyDataContext()
var results = db.storedProcedure(param1, param2, param3)
// Do stuff
当我使用完全相同的参数运行存储过程时,我在2到6秒之间得到结果。该数据库为远程数据库。
但是,当我运行存储过程时,它需要275秒(在调试....之后)!在正常情况下,这会给出以下异常:
[Win32Exception (0x80004005): The wait operation timed out]
[SqlException (0x80131904): Timeout expired.]在操作完成之前经过的超时时间或服务器没有响应。System.Data.SqlClient.SqlConnection。OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction) +1753346 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction) +5295154System.Data.SqlClient.TdsParser。ThrowExceptionAndWarning(TdsParserStateObject, statobj, Boolean callerHasConnectionLock, Boolean asyncClose) +242System.Data.SqlClient.TdsParser。TryRun(RunBehavior RunBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet, bulkCopyHandler, TdsParserStateObject, statobj, boolean &;dataReady) + 1682System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () + 59System.Data.SqlClient.SqlDataReader.get_MetaData () + 90System.Data.SqlClient.SqlCommand。FinishExecuteReader(SqlDataReader ds, RunBehavior RunBehavior, String resetOptionsString) +365System.Data.SqlClient.SqlCommand。RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior RunBehavior,布尔返回流,布尔异步,Int32超时,任务&task, Boolean asyncWrite) +1325System.Data.SqlClient.SqlCommand。RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior RunBehavior,布尔返回流,字符串方法,TaskCompletionSource ' 1完成,Int32超时,任务&task, Boolean asyncWrite) +175System.Data.SqlClient.SqlCommand。RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior RunBehavior, Boolean returnStream, String method) +53System.Data.SqlClient.SqlCommand。ExecuteReader(CommandBehavior行为,字符串方法)+134System.Data.SqlClient.SqlCommand。ExecuteDbDataReader(CommandBehavior行为)+41System.Data.Common.DbCommand.ExecuteReader () + 12System.Data.Linq.SqlClient.SqlProvider。执行(Expression query, QueryInfo QueryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) +1306System.Data.Linq.SqlClient.SqlProvider。ExecuteAll(Expression query, QueryInfo[] QueryInfo, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) +118 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider. QueryInfo, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries。执行(表达式查询)+342System.Data.Linq.DataContext。ExecuteMethodCall(Object instance, MethodInfo, MethodInfo, Object[] parameters) +83
所有其他存储过程都以同样的方式调用,但没有一个有这个问题。远程DB管理员说他可以在超时发生之前看到调用的开始和结束,所以它似乎与Linq接收到数据后的步骤有关。
有没有人经历过这种情况,有什么想法如何解决它?
我已经尝试从dmbl文件中删除SP并重新添加它。它注意到其中一个值从十进制变成了双精度,但除此之外都是一样的。
和往常一样,昨天还很好!提前感谢。
好了,我终于找到了这个问题的真正答案。SSMS通常使用ARITHABORT ON,代码通常使用ARITHABORT OFF——这基本上是一个选项,用于处理代码中的数学行出现错误时会发生什么——例如除以0。
这里最重要的是,这两种方法有不同的执行计划——这就是为什么同样的事情在网站上(随机地)比在SSMS上花费更长的时间。
执行计划是根据第一次使用的估计编译的,所以你随机发现的是执行计划以一种糟糕的方式缓存,适合你的第一个查询,但对随后的查询却很糟糕。这就是这里发生的事情,也是为什么它突然又开始工作了——在存储过程更改后创建了一个新的查询计划。
最后,我们在存储过程中使用了WITH RECOMPILE——因此没有有效地重用执行计划,但是我们没有注意到任何差异,并且从那时起问题就没有发生过。
导致这个问题的原因是依赖于Linq.Table
我的解决方案是将Count()结果赋值给一个局部变量,并在循环中使用它,这样Count()就不会在每次迭代时重新执行查询。我想其他人也会遇到这个问题,如果他们依赖内置的Linq聚合函数,将重新执行缓慢的查询。