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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 08:20:33