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 以上既是缓存的实现,和缓存依赖的具体实现,记下供以后在项目中使用!