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

遗漏await关键字引发Cannot access a disposed context错误的原因咨询

为什么遗漏await会导致数据库上下文已释放错误?

错误信息

Cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'OrderDbContext'. 

经排查,仅需在控制器Action中调用_mediator.Send(checkoutCommand);前添加await关键字,错误即可消失。以下是相关代码:

控制器Action:

public async Task<IActionResult> Checkout(CheckoutOrderCommand checkoutCommand)
{
    var id = _mediator.Send(checkoutCommand); // 此处遗漏了await
    return CreatedAtRoute("Get Order by Id", id);
}

CQRS MediatR命令处理器:

public class CheckoutOrderCommandHandler : IRequestHandler<CheckoutOrderCommand, int>
{
    private readonly IOrderUow _orderUow;
    private readonly IMapper _mapper;

    public CheckoutOrderCommandHandler(IOrderUow orderUow,
        IMapper mapper)
    {
        _orderUow = orderUow;
        _mapper = mapper;
    }


    public async Task<int> Handle(CheckoutOrderCommand request, CancellationToken cancellationToken)
    {
        var order = _mapper.Map<Order>(request);
        
        // 填充基础实体字段
        order.CreatedBy = Constants.CurrentUser;
        
        // 创建新订单
        var newOrder = await _orderUow.AddOrderAsync(order);
        
        return newOrder.Id;
    }
}

工作单元实现:

public class OrderUow : IOrderUow
{
    private readonly OrderDbContext _orderContext;
    public OrderUow(OrderDbContext orderContext)
    {
        _orderContext = orderContext;
    }
    
    public async Task<Order> AddOrderAsync(Order order)
    {
        try
        {
            await _orderContext.Orders.AddAsync(order);
            await _orderContext.SaveChangesAsync();                
        }
        catch (Exception ex)
        {

        }
        return order;
    }
}

核心原因

  • ASP.NET Core中,OrderDbContext默认是Scoped生命周期:每个HTTP请求对应一个上下文实例,请求结束时DI容器会自动释放该实例。
  • 遗漏await时,控制器Action会直接拿到_mediator.Send返回的Task<int>对象,立刻执行return语句。此时ASP.NET Core判定请求处理完成,会立即释放当前请求范围内的所有Scoped服务,包括OrderDbContext。
  • 但MediatR的命令处理器此时仍在后台异步执行Handle方法,其中的_orderUow持有的OrderDbContext已经被释放,后续调用_orderContext.Orders.AddAsync和SaveChangesAsync时,就会触发"无法访问已释放的上下文实例"的错误。
  • 添加await后,Action会等待MediatR的异步任务完全执行完毕才返回响应。此时OrderDbContext会等到所有异步操作完成后,才在请求结束时被DI容器释放,不会出现上下文已释放的问题。

内容的提问来源于stack exchange,提问作者Tech with Thiru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:06:29