System.Web.Caching.Cache 是 ASP.NET 應用程式層級的快取物件,提供記憶體內快取、依賴關係、絕對/滑動過期、優先權、移除回呼等豐富功能。優於 Application 物件:支援自動過期更新、執行緒安全、記憶體壓力下自動淘汰。
Cache 核心優勢對比
| 特性 | Cache | Application |
| 自動過期/更新 | 支援 | 不支援 |
| 執行緒安全 | 是 | 否(需自行鎖定) |
| 記憶體管理 | 自動淘汰 | 無 |
| 檔案/快取依賴 | 支援 | 不支援 |
| 移除通知回呼 | 支援 | 不支援 |
常用方法與屬性
Add(key, value, ...):新增,Key 存在則失敗回傳舊值
Insert(key, value, ...):新增或覆蓋(常用)
Remove(key):移除指定項目
Get(key) / [key]:取得值
Count:快取項目數
Insert 完整參數詳解
public object Insert(string key, object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback)
| 參數 | 說明 | 常用值 |
| key | 快取鍵值 | "ProductList" |
| value | 快取物件 | DataTable, List<T>, 自訂類別 |
| dependencies | 依賴項(檔案、SQL、其他快取鍵) | new CacheDependency(Server.MapPath("~/data.xml")) |
| absoluteExpiration | 絕對過期時間 | DateTime.Now.AddHours(1) |
| slidingExpiration | 滑動過期間隔(存取後重置) | TimeSpan.FromMinutes(20) |
| priority | 淘汰優先權 | CacheItemPriority.Normal / High / NotRemovable |
| onRemoveCallback | 移除時回呼 | OnCacheRemoved 方法 |
關鍵:絕對過期 vs 滑動過期
- 絕對過期:固定時間點失效,
absoluteExpiration = DateTime.Now.AddMinutes(30), slidingExpiration = Cache.NoSlidingExpiration
- 滑動過期:每次存取延長壽命,
absoluteExpiration = Cache.NoAbsoluteExpiration, slidingExpiration = TimeSpan.FromMinutes(10)
- 兩者不可同時設定:會拋出
ArgumentException
實務範例:定時自動重載的商品清單
public static class ProductCache {
private const string CacheKey = "AllProducts";
private static readonly TimeSpan RefreshInterval = TimeSpan.FromMinutes(30);
public static List GetProducts() {
var products = HttpRuntime.Cache[CacheKey] as List;
if (products == null) {
products = LoadProductsFromDB();
// 使用 Insert 覆蓋,設定絕對過期 + 移除回呼觸發重載
HttpRuntime.Cache.Insert(CacheKey, products, null,
DateTime.Now.Add(RefreshInterval),
Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
OnProductsRemoved);
}
return products;
}
private static List LoadProductsFromDB() {
// 實際查詢資料庫邏輯
return ProductDAO.GetAll();
}
private static void OnProductsRemoved(string key, object value, CacheItemRemovedReason reason) {
// 非移除原因(過期/依賴變更)時,背景重載
if (reason != CacheItemRemovedReason.Removed) {
// 避免阻塞請求,使用 ThreadPool 或 Task 執行重載
ThreadPool.QueueUserWorkItem(_ => {
var fresh = LoadProductsFromDB();
HttpRuntime.Cache.Insert(CacheKey, fresh, null,
DateTime.Now.Add(RefreshInterval),
Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
OnProductsRemoved);
});
}
}
}
CacheDependency 進階應用
// 1. 檔案依賴:XML/JSON 設定檔異動自動失效
var dep = new CacheDependency(Server.MapPath("~/Config/settings.xml"));
Cache.Insert("Settings", settings, dep, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);
// 2. SQL 快取依賴 (SqlCacheDependency):資料表異動自動失效
// 需啟用 SQL Server Service Broker 與 aspnet_regsql -et -d DB -t Table
var sqlDep = new SqlCacheDependency("Northwind", "Products");
Cache.Insert("Products", products, sqlDep, ...);
// 3. 多重依賴:任一觸發即失效
var aggregate = new AggregateCacheDependency();
aggregate.Add(fileDep);
aggregate.Add(sqlDep);
Cache.Insert("Data", data, aggregate, ...);
效能與最佳實務
- 快取不可變更物件(或深拷貝),避免多執行緒競態修改
- 大型物件考慮分割快取,減少大物件堆 (LOH) 壓力
- 監控
Cache.TotalMemoryLimit 與 Cache.EffectivePercentagePhysicalMemoryLimit
- 移除回呼中避免耗時操作,必要時併發重載防止雪崩效應