2008/06/11

[ASP.Net]使用System.Web.Caching做網頁資料的Cache

因為Asp.Net中常被使用的 <sqldatasource>, 並無 Exception Handle 的機制.
所以就算用了 <sqldatasource> 的 Caching, 可能還是有某種程度的風險.
例如: 在 Caching 時間到的時候, 剛好資料庫無法連線.
概念上簡單地說, 就是當 Caching 出錯時, 能保留上一次所儲存的資料, 以讓網頁正常運作.

  1. 在 Page_Load 的時候, 檢查 Cache 中的資料是否存在, 若不存在, 則開始進行 Cache 資料的儲存:
    static string st_strProductsKey = "ProductsCache";
    if (Cache.Get(st_strProductsKey) == null)
    {
        AddToCache();
    }
  2. 設計一個設定 Cache 的函式:
    /// <summary>
    /// 將Products資料表加入Cache, 設定失效間隔為30分鍾
    /// </summary>
    private void AddToCache()
    {
        DataTable tblProducts = new DataTable();
        try
        {
            //將Products表格的資料存至DataTable
            SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Products", 
                ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);
            adapter.Fill(tblProducts);
        }
        catch (Exception e)
        {
            //如果發生錯誤, 取上次Cache的資料
            tblProducts = (DataTable)Cache.Get(st_strProductsKey);
        }
        //當tblProducts不是null的時候再設定Cache.
        if (tblProducts != null)
        {
            //設定一個Cache失效時的Callback函式
            CacheItemRemovedCallback onProductsRemovedCallback = new CacheItemRemovedCallback(ARE01DsRemoved);
            Cache.Insert(st_strProductsKey, tblProducts, null, DateTime.Now.AddMinutes(30), 
                Cache.NoSlidingExpiration, CacheItemPriority.Default, onProductsRemovedCallback);
        }
    }
  3. 設計一個 Cache 失效時的 Callback 函式:
    /// <summary>
    /// 當ProductsCache被移除掉時,所觸發的事件->呼叫AddToCache()進行Cache
    /// </summary>
    /// <param name="key"></param>
    /// <param name="val"></param>
    /// <param name="reason"></param>
    private void ARE01DsRemoved(string key, object val, CacheItemRemovedReason reason)
    {
        if (key.Equals(st_strProductsKey, StringComparison.OrdinalIgnoreCase))
        {
            AddToCache();
        }
    }
後記:
這個做法並不是百分百保證資料依然可用, 因為如果第一次 Cache 失敗, 此 Cache 就失效.

沒有留言: