.NET Core 6 Web API连接PostgreSQL报连接正在执行异常问题
问题根因
- 核心报错
Npgsql.NpgsqlOperationInProgressException: The connection is already in state 'Executing'的直接原因是同一个数据库连接被多个操作同时占用。Npgsql连接不支持同一时间执行多条命令,当连接还在执行前一个操作时,新的操作(包括请求结束时框架自动执行的DbContext回收、事务释放、连接关闭逻辑)尝试调用连接,就会抛出该异常。后续出现的数据库连接错误是连接状态被异常破坏后的连带报错,不是问题根源。 - 你贴出的连接字符串本身没有语法错误,不需要先在连接字符串格式上浪费时间排查。
排查修复步骤
按优先级从高到低依次检查:
- 检查DbContext生命周期配置
这是该异常最高发的场景:
- DbContext必须注册为Scoped生命周期(每个请求独立实例),绝对不能注册为Singleton,否则所有并发请求会复用同一个DbContext实例,必然触发连接占用冲突。
- 正确的.NET 6注册写法如下,不要自己封装单例DbContext全局复用:
// Program.cs里的正确配置 builder.Services.AddDbContext<YourDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")) );
- 如果你有Singleton生命周期的服务,不能直接注入Scoped的DbContext,否则DbContext会被单例服务持有、跨请求复用。这种场景要通过
IServiceScopeFactory手动创建作用域获取DbContext,用完自动释放:
public class YourSingletonService { private readonly IServiceScopeFactory _scopeFactory; public YourSingletonService(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public async Task QueryData() { using var scope = _scopeFactory.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<YourDbContext>(); // 执行数据库操作,出using块后DbContext会被自动回收 var data = await dbContext.YourEntities.ToListAsync(); } }
- 检查异步代码写法
所有EF Core、Npgsql的异步方法必须正确加await,禁止不等待异步任务就提前返回,也禁止用.Wait()、.Result等同步阻塞方式调用异步方法。
错误示例:
// 错误:没有await异步查询,请求结束时DbContext开始回收,查询操作还在执行,直接触发连接冲突 [HttpGet] public async Task<IActionResult> GetList() { var list = _dbContext.Users.ToListAsync(); return Ok(); }
正确写法必须给异步操作加await:
[HttpGet] public async Task<IActionResult> GetList() { var list = await _dbContext.Users.ToListAsync(); return Ok(list); }
- 检查同实例并发操作
不要在同一个请求内启动多个并行任务,复用同一个DbContext实例执行数据库操作。错误示例:
// 错误:两个并行任务同时使用同一个DbContext执行查询,抢占同一个连接 var userTask = _dbContext.Users.FirstAsync(u => u.Id == 1); var orderTask = _dbContext.Orders.FirstAsync(o => o.Id == 1); await Task.WhenAll(userTask, orderTask);
这类场景要么顺序await执行两个操作,要么给每个并行操作单独创建独立的DbContext实例。
4. 配置一致性&基础环境检查
- 你贴出的第二个报错里连接的数据库名是
db_name,和你贴的连接字符串里的dbName不一致,检查项目是否存在其他配置源(环境变量、用户机密文件、其他配置文件)覆盖了默认连接字符串,导致连错库。 - 可以在连接字符串中补充连接池配置,降低连接状态异常概率:
"DefaultConnection": "server=localhost;port=5432;userid=user_admin;database=dbName;password=pass@123;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=100;Connection Idle Lifetime=300;"
- 最后确认本地PostgreSQL服务正常运行,5432端口未被占用,用配置的账号密码可以通过psql、pgAdmin等工具正常登录访问目标库,排除服务未启动、账号权限不足的基础问题。
内容的提问来源于stack exchange,提问作者reza.cse08
相关产品推荐
相关产品推荐

