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

.NET 8 Minimal API更改DBContext作用域后遇MemoryCache已释放错误

问题分析与解决方案

核心问题拆解

  1. 将DBContext从Singleton改为Scoped后出现Cannot access disposed object MemoryCache错误:本质并非IMemoryCache被释放(默认Singleton生命周期的服务不会被容器释放),而是AutoMapper映射逻辑与Scoped服务的生命周期冲突——你的AutoMapper配置(Profile)是Singleton,若映射逻辑中错误关联了Scoped的DBContext,请求结束后DBContext被释放,会导致关联操作抛出类似错误(错误信息存在误导)。
  2. 将IMemoryCache改为Scoped后无报错但映射中读不到缓存:因为Scoped缓存仅在当前请求生命周期内有效,而AutoMapper的Profile是Singleton,初始化时无法获取请求级别的Scoped缓存,后续请求的缓存也无法全局共享。

正确解决方案

1. 恢复IMemoryCache的Singleton生命周期

IMemoryCache默认就是Singleton注册,无需额外修改,确保服务注册中没有错误将其改为Scoped:

// 框架默认注册,无需手动编写
builder.Services.AddMemoryCache();

2. 修正AutoMapper读取缓存的方式

AutoMapper的Profile是Singleton,不能直接在构造函数中依赖Scoped服务,读取缓存的逻辑需通过自定义ValueResolver实现,确保依赖注入的正确性:

步骤1:创建缓存读取的ValueResolver

public class UpdatesCacheResolver : IValueResolver<SourceModel, DestinationModel, List<YourUpdateType>>
{
    private readonly IMemoryCache _memoryCache;

    // 注入Singleton的IMemoryCache
    public UpdatesCacheResolver(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public List<YourUpdateType> Resolve(SourceModel source, DestinationModel destination, List<YourUpdateType> destMember, ResolutionContext context)
    {
        if (_memoryCache.TryGetValue("Updates", out List<YourUpdateType> updates))
        {
            return updates;
        }
        // 缓存不存在时返回默认值
        return new List<YourUpdateType>();
    }
}

步骤2:在Profile中注册Resolver

public class YourMappingProfile : Profile
{
    public YourMappingProfile()
    {
        CreateMap<SourceModel, DestinationModel>()
            .ForMember(dest => dest.TargetField, opt => opt.MapFrom<UpdatesCacheResolver>());
    }
}

步骤3:注册Resolver为Singleton

builder.Services.AddSingleton<UpdatesCacheResolver>();
// 确保AutoMapper正常注册
builder.Services.AddAutoMapper(typeof(YourMappingProfile));

3. 优化API接口的请求体处理

无需手动读取Stream,直接用[FromBody]绑定模型,简化代码并避免潜在流处理问题:

public static async Task<Results<Accepted, ProblemHttpResult>> GetUpdates(
    [FromServices] IMemoryCache memoryCache,
    [FromBody] List<YourUpdateType> list) // 自动绑定请求体到模型
{
    try
    {
        memoryCache.Set("Updates", list, new MemoryCacheEntryOptions
        {
            // 可根据需求设置缓存过期时间
            AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
        });
        return TypedResults.Accepted("/");
    }
    catch (Exception ex)
    {
        return TypedResults.Problem(ex.Message);
    }
}

4. 验证Scoped服务的使用范围

确保所有依赖DBContext(Scoped)的操作都在请求生命周期内完成,避免在请求结束后(Scope已释放)执行异步操作访问Scoped服务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:16:20