(理论篇)petshop中缓存运用之我见

petshop中关于缓存的应用很广泛,这里主要是剖析一下实现:

1 先从cs页面开始看起,见代码:

namespace PetShop.Web {
    
    public partial class Products : System.Web.UI.Page {

        protected void Page_Load(object sender, EventArgs e) {
            //get page header and title
            Page.Title = WebUtility.GetCategoryName(Request.QueryString["categoryId"]);
        }
    }
}

WebUtility.GetCategoryName此方法根据商品id取得商品名称,此名称是有缓存的

2 来看WebUtility这个通用类里的实现

 public static string GetCategoryName(string categoryId) {

            Category category = new Category();
            if (!enableCaching)
                return category.GetCategory(categoryId).Name;

            string cacheKey = string.Format(CATEGORY_NAME_KEY, categoryId);

            string data = (string)HttpRuntime.Cache[cacheKey];
            if (data == null) {
                int cacheDuration = int.Parse(ConfigurationManager.AppSettings["CategoryCacheDuration"]);

                data = category.GetCategory(categoryId).Name;

                AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();

                HttpRuntime.Cache.Add(cacheKey, data, cd, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
            }

            return data;
        }

这里的实现很简单,判断缓存是否存在,存在直接返回数据,不存在,则将数据缓存起来,并设置了缓存依赖

(缓存依赖的作用在于数据表更新时,缓存的数据也会自动更新)

3 来看缓存依赖的实现,主要是这一句代码

AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();

意思是取得缓存依赖,如下:

namespace PetShop.CacheDependencyFactory {
    public static class DependencyFacade {
        private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];

        public static AggregateCacheDependency GetCategoryDependency() {
            if (!string.IsNullOrEmpty(path))
                return DependencyAccess.CreateCategoryDependency().GetDependency();
            else
                return null;
        }

        public static AggregateCacheDependency GetProductDependency() {
            if (!string.IsNullOrEmpty(path))
                return DependencyAccess.CreateProductDependency().GetDependency();
            else
                return null;
        }

        public static AggregateCacheDependency GetItemDependency() {
            if (!string.IsNullOrEmpty(path))
                return DependencyAccess.CreateItemDependency().GetDependency();
            else
                return null;
        }
    }
}

读取 <add key="CacheDependencyAssembly" value="PetShop.TableCacheDependency"/>中的配置,若有配置,则通过

DependencyAccess.CreateItemDependency().GetDependency();来获取

4 来看DependencyAccess.CreateItemDependency().GetDependency();的实现

namespace PetShop.CacheDependencyFactory {
    public static class DependencyAccess {
        public static IPetShopCacheDependency CreateCategoryDependency() {
            return LoadInstance("Category");
        }

        public static IPetShopCacheDependency CreateProductDependency() {
            return LoadInstance("Product");
        }

        public static IPetShopCacheDependency CreateItemDependency() {
            return LoadInstance("Item");
        }

        private static IPetShopCacheDependency LoadInstance(string className) {

            string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
            string fullyQualifiedClass = path + "." + className;

            // Using the evidence given in the config file load the appropriate assembly and class
            return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
        }
    }

这里应用到了反射和配置文件相结合的方式,读取应用程序集的配置

 <add key="CacheDependencyAssembly" value="PetShop.TableCacheDependency"/>,

通过反射得到具体类的实例

5 具体反射的缓存实例如下:

namespace PetShop.TableCacheDependency {
    public class Product : TableDependency {

        public Product() : base("ProductTableDependency") { }
    }
}

调用的是父类TableDependency的构造方法来实例化

6 这里才是具体的缓存依赖值,目的就是为具体数据库的具体哪几张表设置缓存依赖,

即这几张表的数据发生变化时,缓存的相应数据也会自动更新过来,优势在此

namespace PetShop.TableCacheDependency {

    public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency {

        // This is the separator that's used in web.config
        protected char[] configurationSeparator = new char[] { ',' };

        protected AggregateCacheDependency dependency = new AggregateCacheDependency();

        protected TableDependency(string configKey) {

            string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"];
            string tableConfig = ConfigurationManager.AppSettings[configKey];
            string[] tables = tableConfig.Split(configurationSeparator);

            foreach (string tableName in tables)
                dependency.Add(new SqlCacheDependency(dbName, tableName));
        }

        public AggregateCacheDependency GetDependency() {
            return dependency;
        }
    }

配置需要设置缓存的数据库,和需要缓存的表

<add key="CacheDatabaseName" value="MSPetShop4"/>
  <!-- *TableDependency lists table dependency for each instance separated by comma -->
  <add key="CategoryTableDependency" value="Category"/>
  <add key="ProductTableDependency" value="Product,Category"/>
  <add key="ItemTableDependency" value="Product,Category,Item"/>

7 以上既是缓存的实现,和缓存依赖的具体实现,记下供以后在项目中使用!

原文地址:https://www.cnblogs.com/jangwewe/p/2985091.html