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

ASP.NET Core应用中Memory Cache未按预期存储键值对问题

问题分析与解决方案

核心问题

你遇到的重复写入缓存问题,根源在于自定义的ContainsKey扩展方法完全不可靠。这个方法通过反射访问MemoryCache内部非公开的EntriesCollection属性来判断缓存键是否存在,但ASP.NET Core的MemoryCache内部实现属于未公开的细节,微软可能在不同版本中修改其结构或属性名称,导致反射无法正确获取缓存条目集合——最终即使缓存已写入,该方法也始终返回false,触发重复加载逻辑。

正确的解决方案

ASP.NET Core的IMemoryCache本身提供了官方推荐的缓存存在性检查方法——TryGetValue,完全不需要自己通过反射实现。

1. 移除自定义的ContainsKey扩展方法

直接抛弃这个依赖内部实现的不稳定方法。

2. 修改中间件的缓存判断逻辑

将SetCache.cs中的判断逻辑替换为TryGetValue:

public sealed class SetCache(RequestDelegate next)
{
    public async Task Invoke(HttpContext context, IHttpContextAccessor httpContextAccessor, IUtilityFactory utilityFactory, IMemoryCache memory)
    {
        // 用TryGetValue检查缓存是否存在,不需要缓存值时可以用out _忽略
        if (!memory.TryGetValue(CommonStatics.Cached, out _))
        {
            ICacheUtility util = utilityFactory.Get<ICacheUtility>();
            ICache cached = new Cache(httpContextAccessor);

            await cached.LoadAsync(context);

            memory.Set<ICache>(CommonStatics.Cached, cached, util.CacheEntryOptions);
        }

        await next(context);
    }
}

3. 优化缓存过期配置(可选)

你的CacheEntryOptions中使用DateTime.Now设置绝对过期时间,每次访问该属性都会生成新的时间戳,可能导致缓存过期时间不一致。建议改用DateTimeOffset.UtcNow(更符合时区规范):

public MemoryCacheEntryOptions CacheEntryOptions => new() 
{ 
    SlidingExpiration = TimeSpan.FromMinutes(20), 
    AbsoluteExpiration = DateTimeOffset.UtcNow.AddDays(2) 
};

额外说明

  • 永远不要依赖框架的内部非公开API实现业务逻辑,这类API没有兼容性保证,版本升级后很容易失效。
  • TryGetValue不仅能判断缓存是否存在,还能直接获取缓存值,是官方推荐的缓存检查方式,性能和可靠性都远高于反射实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:37:14