You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Dapper调用长时间运行存储过程的超时错误

解决ASP.NET Core 6 + Dapper调用长耗时存储过程的超时问题

核心问题分析

  1. 方法命名为GetRiskByYearAsync却使用同步Query方法,违背异步编程规范,导致ASP.NET Core请求上下文阻塞,触发超时。
  2. 存储过程在SSMS中耗时11分钟(660秒),但之前要么用默认30秒超时(commandTimeout: null),要么设置900秒时因同步/异步混用导致连接提前释放,无法获取结果。
  3. 即使命令超时设置足够,ASP.NET Core或IIS的全局请求超时限制也可能截断请求。

分步解决方案

1. 修正异步方法实现

替换同步Query为异步QueryAsync,正确使用await,方法返回Task<IEnumerable<ProjectDetailsByYear>>:

public async Task<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))
    {
        await connection.OpenAsync();
        
        var commandDef = new CommandDefinition(
            sql: "proc_GetProjectDetailsByYear",
            parameters: parameters,
            commandType: CommandType.StoredProcedure,
            commandTimeout: 720 // 设为12分钟,比存储过程耗时多留缓冲
        );

        var projectDetails = await connection.QueryAsync<ProjectDetailsByYear>(commandDef);
        return projectDetails;
    }
}

2. 调整ASP.NET Core全局超时设置

默认Kestrel和IIS的请求超时远短于11分钟,需手动修改:

Kestrel配置(Program.cs)

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(15);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(15);
});

IIS配置(web.config)

部署到IIS时添加请求超时设置:

<system.webServer>
  <aspNetCore requestTimeout="00:15:00" processPath="dotnet" arguments=".\YourProject.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
</system.webServer>

3. 检查SQL Server远程查询超时

SQL Server默认远程查询超时为600秒(10分钟),小于存储过程耗时,需调整:
在SSMS中执行(需管理员权限):

sp_configure 'remote query timeout', 720; -- 设置为12分钟
GO
RECONFIGURE;
GO

若需关闭超时限制,可设为0。

4. 优化存储过程(关键建议)

11分钟的执行时间过长,建议:

  • 检查执行计划,添加缺失索引,避免全表扫描。
  • 优化查询逻辑,若结果集过大,考虑分页返回或开启Dapper流式处理(设置buffered: false)。
  • 排查参数嗅探问题,在存储过程末尾添加OPTION (RECOMPILE)强制重新生成执行计划。

为什么之前设置commandTimeout:900无结果?

异步方法中使用同步Query会阻塞ASP.NET Core请求上下文,耗尽线程池资源,导致请求被提前终止、连接释放,无法获取存储过程的结果集。改用异步QueryAsync并await后,连接会保持到查询完成。

内容的提问来源于stack exchange,提问作者Massey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:00:53