牛骨文教育服务平台(让学习变的简单)
博文笔记

CacheDependency 实现xml文件与缓存数据同步更新

创建时间:2011-12-28 投稿人: 浏览次数:1172
 

用CacheDependency 实现xml文件与缓存数据同步更新

  通常,Web系统的性能瓶颈很可能是由于频繁对数据库或对xml等类型的数据源进行操作导致。为了提高性能,应用程序可以将那些频繁访问的数据存储到缓存中。为了保证数据的正确性,则要有一定的机制来保证当缓存的数据在对应的数据源中被更改时,能够同步更新到缓存中来。ASP.NET 提供了为缓存建立依赖项的机制来完成这一任务。其中涉及到的一个重要的类就是CacheDependency.

  当缓存依赖项变更,ASP.NET将从缓存中移除该缓存。并且可以通过实现CacheItemRemovedCallback 来通知应用程序。因此应用程序就可以做出相应的处理(比如: 为该缓存项读取新的数据)

  缓存依赖项的类型有如下几种:键依赖项,文件依赖项,SQL依赖项,聚合依赖项,自定义依赖项等。其中 SQL依赖项(SqlCacheDenpendency) 的使用可以参考Petshop 4.0

  本文通过实现一个Xml数据源与缓存数据同步更新的Demo来阐述文件依赖项的用法。

Demo描述:

1) 点击链接进入详情页面

2) 详情页面(此页面上有个两个时间,第一个是此次进入详情页面的时间,第二个是从数据源中加载数据的时间。两个时间的差异一般比较大,这是因为数据通常是从缓存读取的)

3)当点击[UpdateCategroy.xml] 或 [UpdateProduct.xml]按钮更新相应的xml文件,CacheDependency触发ASP.NET移除对应的缓存项,当缓存项被移除时,将通过CacheItemRemovedCallback 告知应用程序做出相应处理。此Demo中实现了重新从xml中读取数据更新缓存项的功能。从而实现了xml文件与缓存数据同步更新。

CacheManager 类

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Xml;

/// <summary>
/// Summary description for CacheManager
/// </summary>
public class CacheManager
{
    private static bool _productsRemovedFromCache = false;
    //记录访问从xml读取数据的相关信息
    private static Dictionary<string, string> _logs = new Dictionary<string, string>();
    public static Dictionary<string, string> Logs
    {
        get { return _logs; }
    }

    private static string productxmlPath;
    private static string categoryxmlPath;

    //private static AggregateCacheDependency XmlFileCacheDependencyForBirds = new AggregateCacheDependency();
    //private static AggregateCacheDependency XmlFileCacheDependencyForBugs = new AggregateCacheDependency();  

   static CacheManager() 
   { 
       productxmlPath = HttpContext.Current.Server.MapPath("App_Data/Product.xml");
       categoryxmlPath = HttpContext.Current.Server.MapPath("App_Data/Category.xml");

       //XmlFileCacheDependencyForBirds.Add(
       //    new CacheDependency(HttpContext.Current.Server.MapPath("App_Data/Product.xml")),
       //    new CacheDependency(HttpContext.Current.Server.MapPath("App_Data/Category.xml")));

       //XmlFileCacheDependencyForBugs.Add(
       //    new CacheDependency(HttpContext.Current.Server.MapPath("App_Data/Product.xml")),
       //    new CacheDependency(HttpContext.Current.Server.MapPath("App_Data/Category.xml")));
   }

    //private static AggregateCacheDependency GetAggregateCacheDependency(string categoryKey)
    //{
    //    switch (categoryKey)
    //    {
    //        case "BIRDS":
    //            return XmlFileCacheDependencyForBirds;                
    //        case "BUGS":
    //            return XmlFileCacheDependencyForBugs;   
    //        default:
    //            return null;
    //    }
    //}

    //从缓存中获取项  
    public static List<Product> GetProductsByCategory(string categoryKey)
    {
        //不应在 ASP.NET 页中实现回调处理程序,因为在从缓存中删除项之前该页可能已被释放,因此用于处理回调的方法将不可用,应该在非ASP.NET的程序集中实现回调处理程序。为了确保从缓存中删除项时处理回调的方法仍然存在,请使用该方法的静态类。但是,静态类的缺点是需要保证所有静态方法都是线程安全的,所以使用lock关键字。
        lock (typeof(CacheManager))
        {
            if (HttpContext.Current.Cache[categoryKey] != null)
            {    //存在缓存项,返回缓存值   
                return (List<Product>)HttpRuntime.Cache[categoryKey];
            }
            else
            {   //缓存项不存在,则创建缓存项  
                CacheProducts(categoryKey);
                return (List<Product>)HttpRuntime.Cache[categoryKey];
            }
        }
    }

    //将项以  的名称添加到缓存中,并将该项设置为在添加到缓存中后一分钟过期。  //并且该方法注册 ReportRemoveCallback 方法,以便在从缓存中删除项时进行调用。   
    public static void CacheProducts(string categoryKey)
    {
        lock (typeof(CacheManager))
        {
            AggregateCacheDependency acd = new AggregateCacheDependency();
            acd.Add(
                new CacheDependency(productxmlPath),
                new CacheDependency(categoryxmlPath));

            HttpRuntime.Cache.Add(
                categoryKey,
                CreateProducts(categoryKey),
                acd,
                //An attempt was made to reference a CacheDependency object from more than one Cache entry.
                //GetAggregateCacheDependency(categoryKey),                  
                DateTime.MaxValue,
                new TimeSpan(1, 1, 1),
                System.Web.Caching.CacheItemPriority.Default,
                //使用委托,在缓存删除时调用特定函数来响应。
                ProductsRemovedCallback);
        }
    }

    //创建报告,该报告时缓存项的值  
    private static List<Product> CreateProducts(string categoryKey)
    {
        List<Product> lstProduct = new List<Product>();
        XmlDocument doc = new XmlDocument();
        //HttpContext.Current.Server.MapPath("App_Data/Product.xml") Cache 失效后触发此函数时,HttpContext.Current 可能为Null
        doc.Load(productxmlPath);
        XmlNodeList productNodeList = doc.SelectNodes(string.Format("Products/Product[@CategoryId="{0}"]", categoryKey));
        foreach (XmlNode productNode in productNodeList)
        {
            Product pro = new Product(productNode.Attributes["ProductId"].Value.ToString()
                , productNode.Attributes["Name"].Value.ToString()
                , productNode.Attributes["Descn"].Value.ToString()
                , productNode.Attributes["Image"].Value.ToString()
                , productNode.Attributes["CategoryId"].Value.ToString());
            lstProduct.Add(pro);
        }
        _logs.Remove(categoryKey);
        _logs.Add(categoryKey, string.Format("{1} (Access xml file to get product {0}"s data)", categoryKey, DateTime.Now.ToString()));
        return lstProduct;
    }

    /// <summary>
    /// 当从缓存中删除项时调用该方法  
    /// </summary>
    /// <param name="key">CacheKey</param>
    /// <param name="value">Cache Data</param>
    /// <param name="removedReason">Removed/Expired/Underused/DependencyChanged</param> 
    public static void ProductsRemovedCallback(String key, object value,
        CacheItemRemovedReason removedReason)
    {
        _productsRemovedFromCache = true;
        CacheProducts(key);
    }
}
复制代码


Demo代码下载

参考资料:
http://www.cnblogs.com/wayfarer/archive/2006/11/01/547060.html

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。