cache["key"]直接赋值不生效是因为它依赖httpcontext,仅在page等http上下文中安全;应用启动预热应改用httpruntime.cache;设缓存需按数据特性选绝对或滑动过期;objectdatasource缓存的是业务方法返回对象实例;redis替换时须统一序列化器。

Cache["key"] 直接赋值为什么有时不生效?
因为 Cache 是 ASP.NET Web Forms 时代的内存缓存对象,它依赖于当前 HttpContext。在非页面/非 HTTP 上下文(比如后台线程、Global.asax 的 Application_Start、或 .NET Core 环境)中直接用 Cache["key"] = value 会抛出 NullReferenceException 或静默失败。
- 只在
Page、UserControl、HttpModule等能访问HttpContext.Current.Cache的上下文中安全使用 - 想在应用启动时预热缓存?改用
HttpRuntime.Cache—— 它不依赖请求上下文,全局可用:HttpRuntime.Cache["startup_data"] = GetDataFromDb();
- 注意:IIS 应用池回收后缓存全丢,别指望它持久;也不适合多服务器部署场景
Set 缓存时该选绝对过期还是滑动过期?
选错会导致数据陈旧或频繁重建。绝对过期(DateTime.Now.AddMinutes(10))适合静态配置类数据;滑动过期(TimeSpan.FromMinutes(10))适合用户会话级热点数据,但容易因高频访问“永不过期”,吃光内存。
- 查字典表、国家列表这类几乎不变的数据 → 用绝对过期 + 较长周期(如 24 小时)
- 用户最近浏览商品(按用户 ID 缓存)→ 用滑动过期(如 30 分钟),避免闲置用户占着内存
- 千万别对数据库查询结果盲目设滑动过期——如果底层数据已更新,缓存却因持续访问一直活着,就成脏数据了
ObjectDataSource 绑定时开启缓存,实际缓存的是什么?
不是缓存 SQL 结果,而是缓存 ObjectDataSource 调用的业务方法返回的对象实例。也就是说,它只在方法签名(参数名+类型)完全一致时复用缓存,且要求该方法标记为 [DataObjectMethod(DataObjectMethodType.Select, true)]。
- 必须设置
EnableCaching="true",并指定CacheDuration(单位秒) - 缓存键自动包含所有
SelectParameters值,所以CategoryID=1和CategoryID=2是两个独立缓存项 - 一旦业务方法内部修改了传入参数(比如 List
Add 了元素),下次调用可能拿到被污染的对象引用——缓存的是引用,不是深拷贝
用 Redis 替代 HttpRuntime.Cache 时,最常漏掉的一件事
序列化方式不统一。默认用 Newtonsoft.Json 序列化,但如果某处用 System.Text.Json 写入,另一处用 Json.NET 读取,就会反序列化失败,静默返回 default(T),而你根本看不到异常。
- 所有服务层统一用同一套序列化器,建议封装在
RedisCacheManager内部,禁止外部直接调用IDatabase.StringGet - 缓存复杂对象前先检查是否可序列化:加个
[Serializable]或确保所有属性都有 public getter/setter - 别把
DataTable、DataSet往 Redis 里塞——体积大、序列化慢、跨语言兼容差,换成List<t></t>或Dictionary<string object></string>










