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

访问DbContext触发System.ObjectDisposedException异常,求问题排查

问题分析与修复方案

核心问题:异步Lambda在ForEach中导致上下文被提前释放

你使用pOrders.ForEach(async po => { ... })时,这个异步Lambda属于async void类型方法,而List.ForEach根本不会等待这类异步方法执行完成。外层代码会继续向下执行,当你的异步操作还在处理时,DI容器可能已经将_dbContext回收释放,此时异步代码再访问_dbContext就会触发ObjectDisposedException。

其他潜在问题

  • taskFile可能为null,直接访问taskFile.Id会抛出空引用异常
  • 代码中的jtaskFilesExt是笔误,应为taskFilesExt
  • 所有实体修改后未调用_dbContext.SaveChangesAsync(),修改不会持久化到数据库

修复后的代码

把ForEach替换为普通foreach循环,用await等待每个异步操作完成,同时处理空引用问题,最后保存更改:

var pOrders = await _dbContext.POrders.Where(x => x.ShipId == data.shipNumber).ToListAsync();

foreach (var po in pOrders)
{
    var cardProcess = await _dbContext.CardProcesses.FirstOrDefaultAsync(x => po.Id == x.PurchaseOrderId);
    if (cardProcess != null) // 增加空判断,避免空引用
    {
        cardProcess.SettleStatus = ViewModels.SettleStatus.NA.ToString();
    }

    var shipId = po.ShipId;
    var taskFile = await _dbContext.TaskFiles.FirstOrDefaultAsync(x => x.ShipNumber == shipId);
    if (taskFile == null)
    {
        continue; // 或根据业务逻辑处理taskFile不存在的情况
    }
    
    var taskFilesExt = await _dbContext.TaskFileExts.FirstOrDefaultAsync(x => x.TaskFileId == taskFile.Id);
    if (taskFilesExt != null)
    {
        taskFilesExt.SettlStatus = ViewModels.SettleStatus.NA.ToString(); // 建议直接用枚举值而非ToString
        taskFilesExt.SettleStatus_NA += 1;

        // 修正笔误:jtaskFilesExt改为taskFilesExt
        taskFilesExt.SettleStatus_NA -= model.OldStatus == ViewModels.SettleStatus.NA ? 1 : 0;
        taskFilesExt.SettleStatus_Audited -= model.OldStatus == ViewModels.SettleStatus.Audited ? 1 : 0;
        taskFilesExt.SettlStatus_ReadyToPay -= model.OldStatus == ViewModels.SettleStatus.ReadyToPay ? 1 : 0;
    }
}

// 保存所有修改到数据库
await _dbContext.SaveChangesAsync();

性能优化建议(可选)

如果pOrders数量较多,上述代码会多次访问数据库,性能较差。可改为批量查询,减少数据库往返次数:

var pOrders = await _dbContext.POrders.Where(x => x.ShipId == data.shipNumber).ToListAsync();
var poIds = pOrders.Select(x => x.Id).ToList();
var shipIds = pOrders.Select(x => x.ShipId).Distinct().ToList();

// 批量查询所有需要的CardProcess
var cardProcesses = await _dbContext.CardProcesses.Where(x => poIds.Contains(x.PurchaseOrderId)).ToListAsync();
// 批量查询所有需要的TaskFile
var taskFiles = await _dbContext.TaskFiles.Where(x => shipIds.Contains(x.ShipNumber)).ToListAsync();
var taskFileIds = taskFiles.Select(x => x.Id).ToList();
// 批量查询所有需要的TaskFileExt
var taskFileExts = await _dbContext.TaskFileExts.Where(x => taskFileIds.Contains(x.TaskFileId)).ToListAsync();

foreach (var po in pOrders)
{
    var cardProcess = cardProcesses.FirstOrDefault(x => x.PurchaseOrderId == po.Id);
    if (cardProcess != null)
    {
        cardProcess.SettleStatus = ViewModels.SettleStatus.NA.ToString();
    }

    var taskFile = taskFiles.FirstOrDefault(x => x.ShipNumber == po.ShipId);
    if (taskFile == null)
    {
        continue;
    }
    
    var taskFilesExt = taskFileExts.FirstOrDefault(x => x.TaskFileId == taskFile.Id);
    if (taskFilesExt != null)
    {
        taskFilesExt.SettlStatus = ViewModels.SettleStatus.NA.ToString();
        taskFilesExt.SettleStatus_NA += 1;

        taskFilesExt.SettleStatus_NA -= model.OldStatus == ViewModels.SettleStatus.NA ? 1 : 0;
        taskFilesExt.SettleStatus_Audited -= model.OldStatus == ViewModels.SettleStatus.Audited ? 1 : 0;
        taskFilesExt.SettlStatus_ReadyToPay -= model.OldStatus == ViewModels.SettleStatus.ReadyToPay ? 1 : 0;
    }
}

await _dbContext.SaveChangesAsync();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:25:19