.NET Core 2.2迁6遇NpgsqlOperationInProgressException问题求助
为什么.NET Core 2.2时正常,升级后报错?
PostgreSQL本身从来就不支持MARS(多活动结果集),即同一个数据库连接上不能同时执行多个命令。之前.NET Core 2.2版本正常,是因为旧版本的Npgsql驱动或EF Core存在以下兼容行为:
- 隐式为每个嵌套查询创建新的数据库连接,避免了同一连接的命令冲突;
- 对查询枚举时机的处理不同,外层查询的结果提前加载到内存后才执行内层查询,不会占用同一连接。
升级到.NET 6及最新Npgsql包后,驱动/EF Core的默认行为更严格(比如默认复用连接以提升性能),此时在未完成外层查询枚举的情况下执行内层查询,就会触发PostgreSQL的原生限制,抛出NpgsqlOperationInProgressException。
针对你的代码的解决办法
你的代码问题出在:外层GetData()的查询还在枚举过程中(Select里的逻辑是延迟执行的),就调用GetAdminId()发起新的查询,两者复用了同一个数据库连接。以下是几种可行的解决方式:
1. 提前加载外层结果到内存
先将GetData()的结果执行并加载到内存,再执行内层查询,此时外层查询已释放连接:
// 先ToList()将外层查询结果加载到内存 var dataList = service.GetData().ToList(); var obj = dataList.Select(o => new Object { Id = o.Id, Title = o.Title, AdminId = service.GetAdminId(o.Id) }).ToList();
2. 使用EF Core关联查询(推荐)
通过Include/ThenInclude一次性关联查询所需数据,避免多次数据库访问,这也是EF Core的最佳实践:
假设GetData()返回的实体与entity表有外键关联(比如o.Id对应entity.cId),修改GetData()的查询逻辑:
// 在GetData()中关联查询对应的entity数据 public IQueryable<YourDataEntity> GetData() { return dbContext.YourDataEntities .Include(d => d.关联的Entity表) // 替换为实际的导航属性名 .Where(/* 原有的过滤条件 */); }
然后直接在Select中取关联数据,无需调用GetAdminId():
var obj = service.GetData().Select(o => new Object { Id = o.Id, Title = o.Title, AdminId = o.关联的Entity表.adminId // 直接从关联数据中获取 }).ToList();
3. 投影查询一次性获取所有数据
直接编写联合查询的投影,让数据库一次性返回所有需要的字段,避免多次查询:
var obj = dbContext.YourDataEntities .Join( dbContext.entity.Where(e => e.IsActive), data => data.Id, entity => entity.cId, (data, entity) => new Object { Id = data.Id, Title = data.Title, AdminId = entity.adminId } ).ToList();
4. 为内层查询使用独立连接(不推荐)
如果以上方式无法修改,可以在GetAdminId()中使用独立的DbContext实例,确保内层查询使用新连接:
public int GetAdminId(int id) { // 创建新的DbContext实例,而非复用UnitOfWork的实例 using(var newDbContext = new YourDbContext()) { var obj = newDbContext.entity.GetSingle(x => x.IsActive && x.cId == id); return obj.adminId; } }
此方法会增加数据库连接开销,仅作为临时解决方案。
内容的提问来源于stack exchange,提问作者abhishek sharma

