0

I am working on an ASP.NET Core 6 project. I am using Dapper for my data access. When I used the data access on a long-running stored procedure, I got a timeout error.

This stored procedure usually takes 11 minutes to complete when run in SSMS. When I tried commandTimeout:900, the query was completed right away but returned no result set. I also tried the QueryAsync() method with the same timeout issue.

public IEnumerable<ProjectDetailsByYear> GetRiskByYearAsync(ReportsConfigurationVM reportsConfigurationVM)
{
    var parameters = new DynamicParameters();
    parameters.Add("@ProjectDetailsID", reportsConfigurationVM.ProjectDetailsID, DbType.String);
    parameters.Add("@ProjectNumber", reportsConfigurationVM.ProjectNumber, DbType.String);
    parameters.Add("@ProjectName", reportsConfigurationVM.ProjectName, DbType.String);  

    using (var connection = new SqlConnection(_connectionString))
    {
        var projectDetails = connection.Query<ProjectDetailsByYear> 
                                        ("proc_GetProjectDetailsByYear", 
                                         parameters, 
                                         commandType: CommandType.StoredProcedure, 
                                         commandTimeout: null);
         return (IEnumerable<ProjectDetailsByYear>)projectDetails;
    }
}

This is the error I am getting:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]

An unhandled exception has occurred while executing the request.

Microsoft.Data.SqlClient.SqlException (0x80131904): Execution Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

System.ComponentModel.Win32Exception (258): The wait operation timed out.

at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData() at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData() at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method)
at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
at Dapper.SqlMapper.ExecuteReaderWithFlagsFallback(IDbCommand cmd, Boolean wasClosed, CommandBehavior behavior) in //Dapper/SqlMapper.cs:line 1133
at Dapper.SqlMapper.QueryImpl[T](IDbConnection cnn, CommandDefinition command, Type effectiveType)+MoveNext() in /
/Dapper/SqlMapper.cs:line 1161
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable1 commandTimeout, Nullable1 commandType) in /_/Dapper/SqlMapper.cs:line 801 at Project.DataAccess.Dapper.Reports.Reports.GetRiskByYearAsync(ReportsConfigurationVM reportsConfigurationVM) in D:\Projects\Main\ProjectUpdate\ProjectNew\Project.DataAccess\Dapper\Reports\Reports.cs:line 68 at ProjectNew.Controllers.ProjectReportsController.ProcessReport(ReportsConfigurationVM reportsConfigurationVM) in D:\Projects\Main\ProjectUpdate\ProjectNew\ProjectNew\Controllers\ProjectReportsController.cs:line 82 at lambda_method101(Closure , Object) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

ClientConnectionId:eaa90f24-e94d-4648-a41c-94463b0cf149
Error Number:-2,State:0,Class:11

3
  • Troubleshoot query time-out errors, is showing a default timeout of 0, not null.(Sorry no time to see if that can make a difference) Commented Aug 30, 2024 at 19:35
  • For long running tasks, it would be advisable to move them out of the normal flow of execution and make use of either .NET background tasks or a technology like Quartz / Hangfire or Azure Functions / AWS Lambda. This obviously introduces the question of "How do I notify my user that the report is ready?". The answer to that will depend on your use case. Commented Aug 31, 2024 at 6:53
  • I agree with @Peppermintology. Move it out of the main code. You can use a notification service, maybe using signalR to notify the user about the status of the task. Commented Sep 2, 2024 at 4:21

1 Answer 1

0

Option 1 (easy): Increase SqlConnection.CommandTimeout.

Option 2 (better): improve your SQL and/or DB performance (eg. better choices of indexes).

Without access to schema and query plans I can't be more specific.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.