如何配置.NET缓存使其在API控制器多次调用间保留数据?
嘿,我一眼就看穿了你的问题根源:你的IMemoryCache被错误地注册成了请求级(Scoped)的实例,导致每次HTTP请求都会创建一个全新的缓存,之前请求存的数据自然在后续请求里找不到。
问题出在哪?
看你的Startup.cs代码:
services.AddMemoryCache(); services.AddScoped<IMemoryCache, MemoryCache>(); // 这行是罪魁祸首!
services.AddMemoryCache()已经默认把IMemoryCache注册为**全局单例(Singleton)**了——这才是缓存该有的生命周期,因为缓存需要在所有请求之间共享。但你手动加的AddScoped<IMemoryCache, MemoryCache>()覆盖了默认注册,把缓存改成了每个请求新建一个,那跨请求缓存肯定失效啊!
再加上你的IUserService也是Scoped的,每次请求都会新建一个Service实例,它依赖的缓存也是全新的,这就解释了为什么每次调用都要重新拉取后端数据——缓存从来没真正共享过。
怎么解决?
1. 移除错误的缓存注册
直接删掉Startup.cs里的这一行:
services.AddScoped<IMemoryCache, MemoryCache>();
保留services.AddMemoryCache()就够了,它会帮你注册一个全局唯一的缓存实例。
2. 优化Service里的缓存逻辑(可选但推荐)
你的缓存代码可以更简洁,还能避免重复创建缓存配置:
// 把缓存配置改成静态只读,只初始化一次 private static readonly MemoryCacheEntryOptions _cacheEntryOptions = new MemoryCacheEntryOptions() .SetPriority(CacheItemPriority.NeverRemove); public async Task<UserProfileResponse> GetUserProfile(UserInput input) { string cacheKey = $"{Constants.USER_CACHE_PREFIX}_{input.Inputs.ID}"; // 先查缓存,命中直接返回 if (_cache.TryGetValue(cacheKey, out UserProfileResponse cachedProfile)) { return cachedProfile; } // 缓存没命中,调用慢后端API var configSection = _configuration.GetSection(Constants.Config); var endpoint = configSection[Constants.endpoint]; var functionName = Constants.function; UserProfileResponse freshProfile = await service.SendRequest<UserProfileResponse>(input, endpoint, functionName); // 拿到有效数据就存入缓存 if (freshProfile != null) { _cache.Set(cacheKey, freshProfile, _cacheEntryOptions); } return freshProfile; }
3. 确认服务生命周期
你的IUserService注册成Scoped是没问题的,但它依赖的IMemoryCache必须是Singleton——现在去掉错误注册后,这个依赖关系就正常了,所有请求的Service实例都会共享同一个缓存,缓存数据自然能跨请求命中。
再解释下你看到的现象
首次调用时,当前请求的Scoped缓存里存入了数据,所以能返回给前端;但下一个请求会创建新的Scoped缓存实例,里面是空的,所以不得不重新调用后端API。本质就是缓存从来没在请求之间共享过!
内容的提问来源于stack exchange,提问作者durazno33

