資料庫查詢往往是網站效能瓶頸。對於異動頻率低但讀取頻率高的基礎資料(如新聞分類、商品類別、系統設定),每次請求都查詢資料庫顯然浪費資源。ASP.NET 內建的 SqlCacheDependency 可讓快取在資料表異動時自動失效,達成「資料未變讀快取、資料異動重查資料庫」的最佳平衡。
在 <system.web> 區段加入 <caching> 設定,指定連線字串名稱與自訂快取名稱:
<system.web>
<!-- 其他既有設定 -->
<caching>
<sqlCacheDependency enabled="true" pollTime="6000">
<databases>
<add name="YD_JWC_JAKE" connectionStringName="cachestr" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
<connectionStrings>
<add name="cachestr" connectionString="Data Source=.;Initial Catalog=YD_JWC_JAKE;User ID=sa;Password=sa" />
</connectionStrings>
pollTime="6000":輪詢間隔 6 秒(單位毫秒),資料庫有異動後最多 6 秒快取失效。name="YD_JWC_JAKE":自訂快取資料庫名稱,後續程式碼會用到。connectionStringName:對應 <connectionStrings> 中的 name 屬性。開啟命令提示字元(需系統管理員權限),執行:
aspnet_regsql -C "Data Source=127.0.0.1;Initial Catalog=YD_JWC_JAKE;User ID=sa;Password=" -ed -et -t "T_NewsClass"
-C:資料庫連線字串(C 大寫)。-ed:啟用資料庫快取相依性。-et:啟用資料表快取相依性。-t:指定要監聽的資料表(可重複執行啟用多張表)。執行後,資料庫會建立 AspNet_SqlCacheTablesForChangeNotification 等系統資料表與觸發器,自動追蹤資料異動。
以下範例示範讀取新聞分類,優先從快取取得,無快取才查詢資料庫並建立 SqlCacheDependency:
private void GetNewsClass(int type)
{
string cacheKey = "cacheclass" + type;
object objModel = DataCache.GetCache(cacheKey);
DataTable dt = null;
if (objModel == null) // 快取未命中
{
NewsClass nc = new NewsClass();
dt = nc.GetList("").Tables[0];
objModel = dt;
if (objModel != null)
{
// 建立 SQL 快取相依性:監聽 YD_JWC_JAKE 資料庫的 T_NewsClass 資料表
SqlCacheDependency dep = new SqlCacheDependency("YD_JWC_JAKE", "T_NewsClass");
DataCache.SetCache(cacheKey, objModel, dep);
}
}
else
{
dt = (DataTable)objModel; // 直接使用快取資料
}
// 後續繫結繼覽器、產生選單 HTML 等邏輯...
DataRow[] drs = dt.Select("", "classid");
StringBuilder sb = new StringBuilder();
sb.Append("<ul>");
foreach (DataRow r in drs)
{
// 產生超連結邏輯...
}
sb.Append("</ul>");
Response.Write(sb.ToString());
}
將快取操作封裝為靜態類別,方便全專案呼叫:
public class DataCache
{
public static object GetCache(string CacheKey)
{
return HttpRuntime.Cache[CacheKey];
}
public static void SetCache(string CacheKey, object objObject)
{
HttpRuntime.Cache.Insert(CacheKey, objObject);
}
public static void SetCache(string CacheKey, object objObject, CacheDependency dep)
{
HttpRuntime.Cache.Insert(
CacheKey, objObject, dep,
Cache.NoAbsoluteExpiration,
Cache.NoSlidingExpiration,
CacheItemPriority.Default, null);
}
}
啟用後,首次請求查詢資料庫,後續請求直接讀取記憶體快取,直到資料表有 INSERT/UPDATE/DELETE 異動。對於每分鐘數萬次請求的熱門頁面,資料庫 CPU 使用率可大幅下降 80% 以上。
aspnet_regsql 會自動處理)。pollTime 不宜設太小,避免頻繁輪詢增加資料庫負載。