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

Grpc请求后DbContext被释放,执行UpdateManyQuantity时抛异常

解决ASP.NET中异步Grpc调用后DbContext被释放的问题

问题根源

Scoped生命周期的DbContext默认和请求Scope绑定,处理OrderConfirmEvent或PaymentRejectedEvent时,异步Grpc调用会让当前线程释放原有Scope,等Grpc响应返回后,原DbContext已被DI容器回收,后续执行UpdateManyQuantity自然会抛出ObjectDisposedException。而同步的OrderCreatedEvent全程在同一个Scope内执行,所以不会出现这个问题。

可行解决方案

1. 手动创建新Scope包裹DbContext操作

通过注入IServiceScopeFactory,在Grpc调用完成后,手动创建新Scope,在这个Scope内获取DbContext执行数据库操作,确保操作时DbContext处于有效状态。示例代码:

private readonly IServiceScopeFactory _scopeFactory;
private readonly IOrderGrpcService _orderGrpcService;

// 构造函数注入依赖
public OrderEventHandler(IServiceScopeFactory scopeFactory, IOrderGrpcService orderGrpcService)
{
    _scopeFactory = scopeFactory;
    _orderGrpcService = orderGrpcService;
}

public async Task Handle(OrderConfirmEvent @event)
{
    // 异步调用Grpc获取订单商品
    var orderItems = await _orderGrpcService.GetOrderItems(@event.OrderId);

    // 创建新Scope并获取DbContext
    using var scope = _scopeFactory.CreateScope();
    var dbContext = scope.ServiceProvider.GetRequiredService<YourDbContext>();
    
    // 执行库存更新并保存
    await dbContext.UpdateManyQuantity(orderItems);
    await dbContext.SaveChangesAsync();
}

2. 调整事件处理的Scope生命周期

如果使用MediatR这类事件框架,可以将事件处理器的生命周期配置为Scoped,或者确保整个事件处理流程在同一个Scope内完成。核心是让DbContext的生命周期覆盖从Grpc调用到数据库操作的全流程,避免中途被回收。

注意事项

  • 不要在异步操作外部持有Scoped服务的引用,尤其是DbContext,一旦Scope被释放,引用就会失效。
  • 手动创建Scope时必须用using语句,确保Scope用完后被正确释放,防止资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:55:02