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

缓存场景下Object Disposed异常问题求助

问题描述

我写了一个Cache.cs类,能在指定时长内缓存对象,缓存过期时会通过委托刷新缓存数据。

比如我有个DatumService类,用来存储Datum表的所有行数据。因为这张表几乎不会变更,所以可以安全存在内存里,我设置的缓存过期时间是1小时。

1小时后会调用下面的方法刷新缓存:

/// <summary>
/// Gets all Datum records to be cached.
/// </summary>
private List<Datum> GetDatums()
{
    return ModelContext
        .Datums
        .AsNoTracking()
        .ToList();
}

这个方法通过Entity Framework重新填充缓存里的Datum数据。

现在遇到的问题和ModelContext的实现有关:
DatumService继承自ServiceBase类,这个类注入了IServiceProvider:

private IServiceProvider _serviceProvider { get; set; } = default!;

public ServiceBase(IServiceProvider provider)
{
    _serviceProvider = provider;
}

public ModelContext? ModelContext => _serviceProvider.GetService<ModelContext>();

之前我直接注入ModelContext也会碰到同样的问题。

ModelContext来自微软依赖注入容器,当缓存过期调用刷新方法时,IServiceProvider会抛出“Object Disposed”异常,该怎么解决?

解决方案
  • 避免生命周期不匹配:ModelContext默认是Scoped生命周期,和请求绑定,请求结束后会被容器释放。如果DatumService是Singleton(缓存类通常是单例),直接持有或通过IServiceProvider获取的ModelContext会在请求结束后被释放,后续调用必然抛出已释放异常。

  • 用IServiceScopeFactory创建临时作用域:在ServiceBase中注入IServiceScopeFactory替代IServiceProvider,每次需要使用ModelContext时,创建新的作用域,用完自动释放:

private IServiceScopeFactory _scopeFactory { get; set; } = default!;

public ServiceBase(IServiceScopeFactory scopeFactory)
{
    _scopeFactory = scopeFactory;
}

private List<Datum> GetDatums()
{
    using var scope = _scopeFactory.CreateScope();
    var context = scope.ServiceProvider.GetRequiredService<ModelContext>();
    return context.Datums.AsNoTracking().ToList();
}

每次刷新缓存时都会生成全新的ModelContext实例,用完后通过using自动释放,彻底避免已释放问题。

  • 校验服务生命周期配置:确保DatumService如果是Singleton,注入的服务都是支持Singleton依赖的类型(比如IServiceScopeFactory本身就是Singleton,无冲突)。绝对不要直接将Scoped的ModelContext注入到Singleton服务中,这是DI容器的典型禁忌。

  • 不推荐的备选方案:虽然可以把ModelContext注册为Singleton,但EF的DbContext并非线程安全,会引发并发问题和数据一致性问题,除非你能保证缓存刷新操作是严格单线程执行,否则不要这么做。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 06:12:35