实体框架v1 - 在高流量网站的高峰时段出现“超时过期”例外

时间:2010-09-21 12:49:31

标签: c# .net sql-server entity-framework

我在高流量网站(ASP.NET)的高峰时段遇到这些“System.Data.SqlClient.SqlException”异常。

完整的例外:

SomeMethodName
- Ex.Type: System.Data.UpdateException - Ex.Source: System.Data.Entity 
- Ex.Message: An error occurred while updating the entries. See the inner exception for     details. 
- Ex.StackTrace: 
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager     stateManager, IEntityAdapter adapter) 
at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache) 
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) 
at SomeMethodName() in c:\SomeFileName.cs:line XXXX 
at SomeMethodName() - 
Ex.Type: System.Data.SqlClient.SqlException - Ex.InnerEx.Source: .Net SqlClient Data   Provider - 
Ex.InnerEx.Message: Timeout expired. The timeout period elapsed prior to completion of    the operation or the server is not responding. The statement has been terminated. -
Ex.InnerEx.StackTrace: 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() 
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.ExecuteReader(CommandBehavior behavior) 
at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator  translator, EntityConnection connection, Dictionary`2 identifierValues, List`1  generatedValues) 
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) - 
Ex.InnerEx.Data[HelpLink.ProdName]: Microsoft SQL Server -   Ex.InnerEx.Data[HelpLink.ProdVer]: 10.00.2531
- Ex.InnerEx.Data[HelpLink.EvtSrc]: MSSQLServer - Ex.InnerEx.Data[HelpLink.EvtID]: -2 -   Ex.InnerEx.Data[HelpLink.BaseHelpUrl

我在已安装.NET Framework 4.0的服务器上使用Entity Framework版本1。该数据库是SQL Server 2008 Std 64位。抛出异常的代码如下所示:

using (TransactionScope scope = new TransactionScope())
{
    //Code

    using (DataEntities context = new DataEntities())
    {
        context.AddToListingSet(newListing); //Exception is thrown here
        context.SaveChanges();
    }

    //More code

    scope.Complete();
}

如前所述,这主要发生在高峰时段。在非高峰时段,不会抛出异常。

可能是Entity Framework无法处理它获得的所有数据吗?删除事务代码对我来说不是一个选项。

2 个答案:

答案 0 :(得分:3)

不,问题不在于“实体框架无法处理它所获得的所有数据。”您正在进行INSERT,而不是选择。问题是SQL查询运行的时间比数据库或连接字符串上的超时设置要长,因此它将被终止。

根据您显示的代码,INSERT语句不太可能出错(除非您有触发器或其他代码,但您没有向我们展示)。更有可能是从并发进程运行某些其他查询,该进程锁定正在使用的表。但这是我的猜测。您将不得不进行一些SQL Server性能分析以找到潜在的问题。这里的例外代码似乎是症状,而不是原因。

答案 1 :(得分:2)

我发现为什么我的代码有时会在高峰时段抛出异常。在我的TransactionScope内部,我正在调用

之前做一些系统IO(将上传的图像保存到文件系统)
scope.Complete();

系统IO是一个相对较慢的过程,导致我的列表表锁定更长的时间。

通过在TransactionScope之外移动系统IO,我不再得到例外(在我的情况下,可以将系统IO放在TransactionScope之外)。