缓存

缓存的方式有很多中:

Output Caching 输出缓存

Fragment Caching

Data Caching

SQL Cache

Cache Configuration 配置缓存

一、Output Caching输出缓存有两种方法,一种是基于底层的API技术,一种是基于高层的@OutputCaching。

一旦Output Caching被定制过,网页第一次被访问过的时候就回生成cache,直至请求过期为止。

不说那么多了,先看下petshop中是怎么使用页面缓存的把,嗯,错了,petshop是没使用这种缓存的。那么Output Caching缓存该怎么做呢?

<%@ OutputCache Duration="60" VaryByParam="*" %>

其中Duration是对缓存的页面设置过期时间。VaryByParam应该是指定参数吧,*号表示对所以内容都缓存吧。

她有使用Fragment Caching,即片段缓存。

但其实质跟页面缓存差不多。

petshop的片段缓存不是单纯的缓存,他还用到了SQL Cache,这是.net的新特性,这个缓存对象可以很好解决数据库变化对已缓存页面的改变(这里不多说)。

就拿ProductsControl.ascx这个控件来说把:

在前台导入页面设置:<%@ OutputCache Duration="100000" VaryByParam="page;categoryId" %>

为何VaryByParam的值是page和categoryId呢?categoryId是根据类别来判断要显示的product。但是page我就不明白了(待续)。

下面是ProductsControl.ascx.cs的代码:

public partial class ProductsControl : System.Web.UI.UserControl {

        /// <summary>
        /// Rebind control 
        /// </summary>
        protected void PageChanged(object sender, DataGridPageChangedEventArgs e) {
            //reset index
            productsList.CurrentPageIndex = e.NewPageIndex;

            //get category id
            string categoryKey = Request.QueryString["categoryId"];

            //bind data
            Product product = new Product();
            productsList.DataSource = product.GetProductsByCategory(categoryKey);
            productsList.DataBind();

        }

        /// <summary>
        /// Add cache dependency
        /// </summary>
        protected void Page_Load(object sender, EventArgs e) {
            this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
        }
    }

其中对数据的绑定是没有什么变化,最重要的要看page_Load的:

this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
增加了这句就可以对数据库的表进行实时增删改监控(用词不当吧)吧。

但是petshop还为我们展示了另外一种缓存方法,这种方法要叫什么呢?我查了下应该就是传说中的Date Cache(数据缓存)吧:

且看他们是怎么来做滴(我就拿CategoryDataProxy.cs来说明吧),下面就是这个类的一个方法了:

public static IList<CategoryInfo> GetCategories() {

            Category cat = new Category();

            if (!enableCaching)
                return cat.GetCategories();

            string key = "category_all";
            IList<CategoryInfo> data = (IList<CategoryInfo>)HttpRuntime.Cache[key];

            // Check if the data exists in the data cache
            if (data == null) {
                // If the data is not in the cache then fetch the data from the business logic tier
                data = cat.GetCategories();

                // Create a AggregateCacheDependency object from the factory
                AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();

                // Store the output in the data cache, and Add the necessary AggregateCacheDependency object
                HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(categoryTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
            }

            return data;
        }

其中:private static readonly bool enableCaching = bool.Parse(ConfigurationManager.AppSettings["EnableCaching"]);//true
这种缓存机制是最原始的把,首先我们要从cache[key]就键中找值,如果没有就缓存起来,这种数据缓存在petshop广泛应用。

这边还是来讲讲那个Sql Cache吧,那么首先要先对数据库进行配置,就是对要监控的表进行配置吧:

以PetShop 4.0为例,数据库名为MSPetShop4,则命令为:

aspnet_regsql -S localhost -E -d MSPetShop4 -ed

以下是该工具的命令参数说明:
-?  显示该工具的帮助功能;
-S  后接的参数为数据库服务器的名称或者IP地址;
-U  后接的参数为数据库的登陆用户名;
-P  后接的参数为数据库的登陆密码;
-E  当使用windows集成验证时,使用该功能;
-d  后接参数为对哪一个数据库采用SqlCacheDependency功能;
-t  后接参数为对哪一个表采用SqlCacheDependency功能;
-ed  允许对数据库使用SqlCacheDependency功能;
-dd  禁止对数据库采用SqlCacheDependency功能;
-et  允许对数据表采用SqlCacheDependency功能;
-dt  禁止对数据表采用SqlCacheDependency功能;
-lt  列出当前数据库中有哪些表已经采用sqlcachedependency功能。

以上面的命令为例,说明将对名为MSPetShop4的数据库采用SqlCacheDependency功能,且SQL Server采用了windows集成验证方式。我们还可以对相关的数据表执行aspnet_regsql命令,如:
aspnet_regsql -S localhost -E -d MSPetShop4 -t Item -et
aspnet_regsql -S localhost -E -d MSPetShop4 -t Product -et
aspnet_regsql -S localhost -E -d MSPetShop4 -t Category -et

当执行上述的四条命令后,aspnet_regsql工具会在MSPetShop4数据库中建立一个名为AspNet_SqlCacheTablesForChangeNotification的新数据库表。

 

具体情况请参考petshop的数据库petshop4。完。

 

最后补充一个API缓存(应该是对应上面的sql cache 吧)

其实这种缓存是最原始的缓存吧,先看下在Cache中存储数据的最简单的方法就是使用一个键为其赋值,就像HashTable或Dictionary对象一样: 
   
  Cache["key"] = "value"。

具体我们可以看下petshop中的SQLHelper中对SQLParameter的缓存吧:

首先定义了:paramcache的散型变量        private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

其次,添加缓存:  

       /// <summary>
        /// add parameter array to the cache
        /// </summary>
        /// <param name="cacheKey">Key to the parameter cache</param>
        /// <param name="cmdParms">an array of SqlParamters to be cached</param>
        public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters) {
            parmCache[cacheKey] = commandParameters;//将传过来的SqlParmeter参数存放在散列表中
        }

 

再次,调用。

        /// <summary>
        /// 检索HashTable的参数 HashTable是一个散列值
        /// </summary>
        /// <param name="cacheKey">key used to lookup parameters</param>
        /// <returns>Cached SqlParamters array</returns>
        public static SqlParameter[] GetCachedParameters(string cacheKey) {
            SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];//查看散列表中是否有这个键值

            if (cachedParms == null)
                return null;

            SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];//为什么要复制我就不知道了

            for (int i = 0, j = cachedParms.Length; i < j; i++)
                clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();//这种复制是无法正确判断是深度复制还是浅度复制 但这并不重要

            return clonedParms;
        }


原文地址:https://www.cnblogs.com/huaizuo/p/2179191.html