Web缓存技术

本章导读

缓存主要是为了提高数据的读取速度。因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能。

本章从缓存所在的命名空间“System.Web.Caching”开始,详细介绍框架提供的缓存类和操作方法,主要涉及简单数据的缓存、数据缓存依赖和数据库缓存依赖三个技术要点,最后演示一个完全使用缓存实现数据读取的实例。讲解流程如图16-1所示。


图16-1  缓存命名空间的讲解流程

16.1  System.Web.Caching简介

本节从缓存命名空间的总体简介和组成结构入手,从整体上对System.Web.Caching进行概述。

16.1.1  System.Web.Caching概述

System.Web.Caching是用来管理缓存的命名空间。缓存就是将服务器端的数据暂时保存在客户端,方便用户的读取。缓存命名空间的父级空间是“System.Web”,由此可以看出,缓存通常用于Web网站的开发,包括在B/S项目中的开发。缓存的设计主要是考虑到网络带宽可能会延缓数据的提交和回发,如果将数据保存在客户端,用户可以直接从客户端读取数据,这样数据就是从本地提取的,不会再受网络的影响。

System.Web.Caching命名空间提供与缓存有关的所有操作类,具体包括哪些类将在下一节详细介绍。

16.1.2  System.Web.Caching命名空间内的类组成

缓存命名空间主要提供三种操作:缓存数据对象、对象的缓存依赖和数据库的缓存依赖。其中缓存任何对象都使用一个类Cache,但当缓存发生改变时,普通对象和数据库对象的依赖处理不同。

图16-2罗列的是在三层结构中缓存的部署情况。两个依赖类CacheDependency和SqlCache Dependency主要更改发生变化的缓存数据,起到通知的作用。当数据没有被缓存时,使用Cache类进行添加。

下面根据图16-2的部署,来介绍图中使用的缓存类。这些类的说明如表16-1所示。

 

图16-2  三层结构中缓存的部署图

表16-1  缓存命名空间中的类及其说明

    

    

Cache

对缓存对象的编辑类,其操作包括缓存的增、删、改

CacheDependency

基本缓存对象的依赖,当基本对象发生变化时,更新缓存内容

SqlCacheDependency

数据库缓存对象的依赖,当数据库中的数据变化时,更新缓存内容

16.2  管理缓存的类:Cache类

Cache类用来存储数据对象,并提供方法对这些对象进行编辑。本节主要介绍Cache类包含的方法,以及如何使用这些方法实现数据对象的缓存。

16.2.1  功能说明

Cache类属于字典类,其根据一定的规则存储用户需要的数据,这些数据的类型不受限制,可以是字符串、数组、数据表、Dataset和哈希表等。

使用Cache类的优点是当缓存的数据发生变化时,Cache类会让数据失效,并实现缓存数据的重新添加,然后通知应用程序,报告缓存的及时更新。

16.2.2  语法定义

Cache类的语法定义如下:

public sealed class Cache : IEnumerable

通过其定义可以发现,Cache类是“sealed”定义的类,表示此类被密封,不能被继承。同时Cache类还继承了IEnumerable接口,表示允许对集合中的数据进行枚举操作。

缓存的生命周期随着应用程序域的活动结束而终止,也就是说只要应用程序域依然处于活动状态,缓存就会一直保持,因为每个应用程序域都会创建一个缓存实例。此实例的信息通过HttpContext对象的Cache属性或Page对象的Cache属性获取。

下面的代码演示如何将数组数据添加到缓存中:

ArrayList myarray = new ArrayList();        //创建数组数据

myarray.Add("1.学习园地");

myarray.Add("2.交流论坛");

myarray.Add("3.帮助");

Cache.Add("Category", myarray);        //将数组添加到缓存中

16.2.3  方法详解

Cache类的方法主要提供对缓存数据的编辑操作,如增、删、改等。其中最常用的方法及其说明如表16-2所示。

表16-2  Cache类的主要方法及其说明

    

    

Add

将数据添加到Cache对象

Insert

Cache中插入数据项,可用于修改已经存在的数据缓存项

Remove

移除Cache对象中的缓存数据项

Get

Cache对象中获取指定的数据项,注意返回的是Object类型,需要进行类型转换

GetType

Cache对象中获取数据项的类型,判断数据类型后,方便进行转换

GetEnumerator

循环访问Cache对象中的缓存数据项。注意其返回类型是“IDictionaryEnumerator

技巧:要想修改缓存数据,只需要重新为缓存赋值即可。

最需要注意的是Add方法,其使用语法如下:

public Object Add (

     string key,

     Object value,

     CacheDependency dependencies,

     DateTime absoluteExpiration,

     TimeSpan slidingExpiration,

     CacheItemPriority priority,

     CacheItemRemovedCallback onRemoveCallback

)

在使用Add方法时,以上7个参数是必需的,其代表意义如下:

— 参数“key”代表缓存数据项的键值,必须是唯一的。

— 参数“value”代表缓存数据的内容,可以是任意类型。

— 参数“dependencies”表示缓存的依赖项,也就是此项的更改意味着缓存内容已经过期。如果没有依赖项,可将此值设置为NULL。

— 参数“absoluteExpiration”是日期型数据,表示缓存过期的时间,.NET 2.0提供的缓存在过期后是可以使用的,能使用多长时间,就看这个参数的设置。

— 参数“slidingExpiration”的类型表示一段时间间隔,表示缓存参数将在多长时间以后被删除,此参数与absoluteExpiration参数相关联。

— 参数“priority”表示撤销缓存的优先值,此参数的值取自枚举变量“CacheItemPriority”,优先级低的数据项将先被删除。此参数主要用在缓存退出对象时。

— 参数“onRemoveCallback”表示缓存删除数据对象时调用的事件,一般用做通知程序。

下面的代码演示了如何应用Cache类的这些方法。在使用本代码时需要注意,代码中使用了Arraylist对象,所以需要添加对命名空间“System.Collections”的引用,同时使用Cache类别忘记了添加命名空间“System.Web.Caching”。

    protected void Page_Load(object sender, EventArgs e)

    {

        ArrayList myarray = new ArrayList();         //创建数组数据

        myarray.Add("1.学习园地");

        myarray.Add("2.交流论坛");

        myarray.Add("3.帮助");

        //将数组添加到缓存中——使用Add方法

        Cache.Add("Category", myarray, null, DateTime.Now.AddSeconds(60), TimeSpan.Zero, CacheItemPriority.Normal, null);

        myarray[1] = "2.交流园地";                     //修改数组数据  

        Cache.Insert("Category", myarray);           //使用Insert方法修改缓存数据

        string tmpStr = "这是一个临时数据";

        Cache["tmpdata"] = tmpStr;

        //使用Get方法获取缓存数据

        Response.Write(Cache.Get("tmpdata").ToString()+"<br/>");/

        Cache["tmpdata"] = "这是一个临时字符串";         //重新为缓存赋值的技巧

        Response.Write(Cache.Get("tmpdata").ToString() + "<br/>");

        //使用GetType方法判断缓存数据的类型

        if (Cache["Category"].GetType().Name == "ArrayList")

            Response.Write("类型是数组");

        //使用GetEnumerator方法遍历缓存中的数据

        IDictionaryEnumerator mycache = Cache.GetEnumerator();

        while (mycache.MoveNext())

            Response.Write(mycache.Value + "<br/>");

        Cache.Remove("tmpdata");//使用Remove方法移除缓存的临时数据

}

技巧:在使用GetType方法时,如果要判断类型,需要使用Object.GetType().Name属性获取类型的名称。

上述代码的运行结果如下:

这是一个临时数据

这是一个临时字符串

类型是数组这是一个临时字符串

System.Collections.ArrayList

其中在读取类型为ArrayList的数据时,由于没有进行类型转换,所以取出的是类型为“System.Collections.ArrayList”的对象。本书会在本节最后的实例中介绍如何读取数组的详细内容。

16.2.4  属性详解

Cache类的属性主要用来获取缓存数据的一些基本信息,如缓存的项总数、指定位置的缓存项等。本书主要介绍两个属性:Count和Item。

Count用来获取缓存中所有的项的总数。使用方法如下:

Response.Write(Cache.Count);

Item用于返回指定项的内容,一般继承“IEnumerable”接口的类都有这样的属性,注意项需要使用“[ ]”包装。其使用方法如下:

Response.Write(Cache[“Category”].ToString());

16.2.5  典型应用:实现数据的缓存快速读取功能

Cache主要用来缓存使用频率高且不需经常更新的数据。本例实现一个目录列表的缓存。为了简便,列表的内容并没有从数据库中读取,而是保存在一个ArrayList对象中。

本例的目的是将目录列表填充到下拉框中,当缓存失效后,目录列表的内容为空。演示的步骤如下所述。

  在VS2005中创建一个网站,命名为“CacheSample”。

  打开默认生成的Default.aspx页,在其中添加一个下拉列表框和一个按钮。

  按F7键切换到页面的代码视图。不要忘记对命名空间的引用,代码如下:

using System.Web.Caching;

using System.Collections;

   在“Page_Load”事件中判断是否存在目录缓存,如果没有,则将目录添加到缓存中。详细代码如下所示,其中目录列表的保存时间是5秒。

protected void Page_Load(object sender, EventArgs e)

{

    if (!Page.IsPostBack)

    {

       ArrayList myarray = new ArrayList();//假设ArrayList的内容来自数据库

        myarray.Add("古代历史");

        myarray.Add("当代文学");

        myarray.Add("流行小说");

        myarray.Add("武侠小说");

        if (Cache["Categorys"] == null)  //判断是否存在缓存

        {

            //如果缓存不存在,则添加——保存时间是5秒

            Cache.Add("Categorys", myarray, null, DateTime.Now.AddSeconds(5),

                TimeSpan.Zero, CacheItemPriority.Normal, null);

        }

    }

}

  回到设计视图,双击按钮控件,切换到按钮的事件代码中。

  在按钮的双击事件中,需要判断是否有目录的缓存,有则在下拉框中显示目录内容,没有则清空下拉框。详细代码如下:

protected void Button1_Click(object sender, EventArgs e)

{

    if (Cache["Categorys"] != null)        //判断缓存是否失效

    {

        //如果没有失效,则取出缓存的列表,注意类型的转换。

        DropDownList1.DataSource = (ArrayList)Cache["Categorys"];

        DropDownList1.DataBind();

    }

    else

    {

        DropDownList1.Items.Clear();   //如果已经失效,则清空列表

    }

}

  按Ctrl+S组合键保存所有的代码,再按F5键运行程序。在5秒以内如果单击按钮,则正常显示目录列表,如果超过5秒,则缓存对象已经不存在,所以下拉列表框的内容为空。

本节主要介绍了Cache类的使用方法,其中并没有涉及缓存依赖内容,即当实际数据改变时,缓存是否随着改变。下一节将通过学习“CacheDependency”类了解缓存依赖的详细实现。

16.3  缓存依赖类:CacheDependency类

CacheDependency类是架设在Cache类和实际数据之间的桥梁。本节将详细介绍如何利用CacheDependency类实现数据缓存的及时更新。

16.3.1  功能说明

CacheDependency类被称为是缓存依赖类,其具体意义表现在当缓存对象的实际数据发生改变时,它能及时通知缓存对象。例如缓存对象“Category”保存的是一个XML文件的数据,如果XML文件发生了变化,那么系统通过CacheDependency类就会及时更新缓存对象“Category”的内容,这样就能保证用户读取的永远是最新的数据。

16.3.2  语法定义

CacheDependency类的语法定义如下:

public class CacheDependency : IDisposable

其中继承了接口“IDisposable”,此接口主要用来定义释放分配的非托管资源的方法。继承此接口必须实现方法Dispose,以实现资源的释放。

CacheDependency类的构造函数实现了8个重载,下面的代码列出了这些重载的函数,并详细说明了各函数的参数。了解这些函数就可以知道CacheDependency究竟能为缓存带来什么优势。

    //假设缓存的来源文件是当前目录下的data.xml文件

    //缓存依赖的文件路径

    CacheDependency mydep = new CacheDependency("data.xml");

    //缓存依赖的文件可以有多个

    CacheDependency mydep1=new CacheDependency(new string []{"data.xml","data1.xml"});

    //检查缓存依赖更改的依据时间

    CacheDependency mydep2 = new CacheDependency("data.xml", DateTime.Now);

    //检查多个依赖文件更改的依据时间

    CacheDependency mydep3 = new CacheDependency(new string[] { "data.xml", "data1.xml" }, DateTime.Now);

    //检查依赖多个文件,也依赖多个缓存键值

    CacheDependency mydep4 = new CacheDependency(new string[] { "data.xml", "data1.xml" },

        new string[] { "Category", "Category1" });

    //关联依赖,还可以依赖于另一个文件缓存依赖

    CacheDependency mydep5 = new CacheDependency(new string[] { "data.xml", "data1.xml" },

        new string[] { "Category", "Category1" }, mydep);

    //文件和键值上次修改的依据时间

    CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml", "data1.xml" },

        new string[] { "Category", "Category1" }, DateTime.Now);

    //文件、另一个缓存依赖和键值上次修改的依据时间

    CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml", "data1.xml" },

new string[] { "Category", "Category1" }, mydep,DateTime.Now);

16.3.3  方法和属性

虽然CacheDependency类完成了很重要的功能,但其组成结构却比较简单,主要有两个属性和一个方法。

— 属性“HasChanged”:判断CacheDependency对象是否已更改。

— 属性“UtcLastModified”:返回上次依赖项的修改日期

— 方法“Dispose”:释放CacheDependency对象所占有的资源。因为缓存类继承了接口“IDispose”,所以必须实现此方法。

由于缓存类的构成比较简单,本节并没有给出演示代码,属性和方法的使用将在下一节的实例中演示。

注意:只有Cache类的Insert和Add方法才可以为缓存添加依赖项。

16.3.4  典型应用:用CacheDependency获取最新的数据

本例主要演示如何使用CacheDependency类实现数据的及时更新。实例中使用一个GridView控件显示XML文件的数据,当XML文件的数据发生改变时,客户端可以及时更新。其实现的功能如图16-3所示。

 

图16-3  用CacheDependency获取最新数据的功能实现图

演示的详细步骤如下所述。

     打开VS2005,创建一个网站,命名为“CacheDependencySample”。

     在网站根目录下,添加一个XML文件,用来为控件提供数据,内容如下:

<?xml version="1.0" encoding="utf-8" ?>

<book>

     <bookinfo>

         <name>英国古代</name>

         <price>28.00</price>

     </bookinfo>

     <bookinfo>

         <name>中国历史</name>

         <price>20.00</price>

     </bookinfo>

</book>

     打开默认生成的Default.aspx页,添加一个GridView控件和一个按钮控件。

     按F7键切换到窗体的代码视图,在Page_Load事件中书写生成缓存的代码。详细内容如下:

private static CacheDependency mydepen;

protected void Page_Load(object sender, EventArgs e)

{

    if (!IsPostBack)

    {

        //创建XML数据源

        DataSet myds = new DataSet();

        //数据源来自文件data.xml

        myds.ReadXml(this.MapPath(Request.ApplicationPath + @"/data.xml"));

        //判断是否存在缓存

        if (Cache["BOOKS"] == null)

        {

            //创建缓存依赖

           mydepen = new CacheDependency(this.MapPath(Request.ApplicationPath

                + @"/data.xml"));

            //添加缓存项

            Cache.Add("BOOKS", myds, mydepen, DateTime.Now.AddSeconds(10), TimeSpan.Zero,

                CacheItemPriority.Normal, null);

        }

    }

}

注意:使用XML文件读取方法,必须添加XML操作方法所在的命名空间“System.Xml”。

     切换回设计视图,再双击按钮控件,此时光标停靠在按钮的Click事件内。在此事件内书写代码,判断XML文件的数据是否已更新,如果已更新则给出提示,并重新添加缓存依赖项,否则直接从缓存读取GridView控件的数据。

     在“Button1_Click”事件内书写的详细代码如下:

protected void Button1_Click(object sender, EventArgs e)

{

    //判断缓存是否发生了变化

    if (mydepen.HasChanged)

    {

        Response.Write("Sorry,数据发生了变化!上次修改时间是:" + mydepen.UtcLastModified);

    }

    //判断缓存项是否还在

    if (Cache["BOOKS"] == null)

        {

        //重新设置缓存项

            DataSet myds = new DataSet();

            myds.ReadXml(this.MapPath(Request.ApplicationPath + @"/data.xml"));

            mydepen = new CacheDependency(this.MapPath(Request.ApplicationPath + @"/ data.xml"));

        Cache.Add("BOOKS", myds, mydepen, DateTime.Now.AddSeconds(10), TimeSpan.Zero,

CacheItemPriority.Normal, null);

        }

        GridView1.DataSource = Cache["BOOKS"];

        GridView1.DataBind();

}

注意:当XML文件发生改变后,其实缓存依赖和缓存项都被移除了,必须重新定义。

     按Ctrl+S组合键保存代码的修改。再按F5键运行程序,单击“获取数据”按钮,GridView就会显示XML文件的内容。

     程序运行正常后,在后台修改XML文件的内容,然后再单击“获取数据”按钮,则出现更改数据的提示,同时GridView显示了新的内容。图16-4和图16-5是数据更改前和更改后的效果对比。

                   

           图16-4  初次获取的数据效果图                                图16-5  更改数据后的显示效果图

16.4  数据库缓存依赖类:SqlCacheDependency类

数据库缓存依赖主要解决的是当数据库的内容发生改变时,如何及时通知缓存,并更新缓存中的数据的问题。本节就介绍如何使用SQL Server 2005和.NET 2.0实现数据库的缓存依赖。

16.4.1  功能说明

SqlCacheDependency类的使用需要结合SQL Server 2005数据库,目前还没有Oracle数据库的缓存依赖。

16.4.2  语法定义

SqlCacheDependency类的使用语法如下:

public class SqlCacheDependency : IDisposable

其中继承了接口“IDisposable”,此接口主要用来定义释放分配的非托管资源的方法。继承此接口必须实现方法Dispose,用来实现资源的释放。

SqlCacheDependency类主要的构造函数如下:

public SqlCacheDependency(string database,string table)

其中参数一代表要启用缓存的数据库,参数二表示缓存的表。在实际使用过程中,只需要指明缓存的数据库和表即可。

16.4.3  方法和属性

SqlCacheDependency类的方法和属性同CacheDependency类相同,主要有三个。

—  HasChanged:判断数据库缓存依赖是否发生了变化。

—  UtcLastModified:获取缓存依赖上次更改的时间。

—  Dispose:释放缓存依赖所占用的资源。

这三个成员的使用方法同CacheDependency类的成员相似,本节不再赘述。

在下节要介绍的使用实例中,将不再使用代码的方式实现缓存依赖,而是使用“OutputCache”在.NET 2.0中提供的SqlCacheDependency参数实现数据库表的缓存。如果要使用编程的方式实现此功能,可参考CacheDependency类的实例。

16.4.4  使用SqlCacheDependency类的操作流程

要实现数据库缓存依赖,必须结合数据库的操作。在使用数据库缓存依赖前,必须进行5步操作。详细流程如图16-6所示。

只有具备了上述条件,才可以正常地使用数据库缓存依赖。下一节将结合这5步操作演示如何实现数据库的缓存依赖。

            图16-6  使用数据库缓存依赖的流程

16.4.5  典型应用:获取数据库表最新数据的实例

本例要实现的功能是当数据库的内容发生变化时,保存在缓存中的数据项被更新。具体演示的步骤如下所述。

     在数据库中创建数据库“testCache”。

     在数据库“testCache”中添加表“CacheTable”,其信息如表16-3所示。

表16-3  CacheTable表的信息

    

字段类型

    

id

int

自增长数据标识

Name

nvarchar(20)

书名

bookPublish

nvarchar(50)

出版社

Price

decimal(6,2)

书的价格

     为数据库启用缓存通知。打开“开始”|“所有程序”|“Microsoft Visual Studio 2005”|“Visual Studio Tools”|“Visual Studio 2005命名提示”菜单命令。

   输入如下命令,其中“-ed”和“-et”分别代表启用缓存依赖数据库和启用缓存数据表。
         aspnet_regsql.exe -S  SqlServer服务器 -E -ed -d  数据库名称 -et -t  表名
         注意如果使用的数据库验证方式是“SQL Server身份验证”,则需要使用如下的启动命令:
         aspnet_regsql.exe -S  SqlServer服务器  -U <Username> -P <Password> -ed -d 数据库名称 -et -t 表名
        输入命令后,按回车键。如果执行成功,效果如图16-7所示。

     打开VS2005,新建一个网站,命名为“SqlCacheDependency”。

     按F5键运行程序,主要目的是生成一个默认的Web.Config文件。然后关闭运行的程序。

     在Web.config中配置数据库连接字符串,代码如下:

     <connectionStrings>

         <add name="TestCacheConnectionString" connectionString="Data Source=CGJ-57F90 CCA64C\sqlexpress;Initial Catalog=testCache;Integrated Security=True" providerName= "System.

Data.SqlClient"/>

     </connectionStrings>

  

  图16-7  启用数据库缓存依赖成功的提示图

    在“system.web”节点内,添加数据库缓存依赖的配置,详细代码如下所示。注意配置中的“connectionStringName”属性,要与前面创建的数据库连接字符串的名字相对应。

<caching>

     <sqlCacheDependency enabled = "true" pollTime = "1000" >

         <databases>

              <add name="testCache"

                 connectionStringName="TestCacheConnectionString"

                 pollTime = "1000"      />

         </databases>

     </sqlCacheDependency>

</caching>

     按Ctrl+S组合键保存配置文件的更改。

     打开默认生成的Default.aspx页,在设计视图中添加一个GridView控件,用来显示从数据库获取的数据。再添加一个Literal控件,主要用来显示时间,通过时间判断显示的是否是缓存中的数据。

     为GridView配置数据源。单击其任务列表,在“选择数据源”下拉框中,单击“新建数据源”命令,打开数据源的配置向导。

     在打开的数据源类型窗口中,选择“数据库”,单击“确定”按钮,出现选择连接字符串窗口,通过下拉列表选择刚刚创建的“TestCacheConnectionString”连接串。

     单击“下一步”按钮,出现“配置Select语句”对话框,在“列”列表框中选择“*”,表示选中所有列。

     单击“下一步”按钮出现测试查询对话框,然后单击“完成”按钮。

     按F7键切换到到代码视图,在“Page_Load”事件中添加如下代码(主要是显示当前的时间,用来判断是否是缓存数据):

Literal1.Text = DateTime.Now.ToString();

     按Ctrl+S组合键保存当前页的设计,再按F5键运行程序。当刷新页面时,可以看到时间是不断变化的,这说明数据并没有来自缓存。

     打开Default.aspx页,在源代码视图的“<@page ”行下面,添加如下所示代码。其中使用的参数“SqlDependency”,就是用来添加数据库缓存依赖的。

 <%@ OutputCache Duration="3600" SqlDependency="testCache:CacheTable" VaryByParam="none" %>

注意:Duration参数是表示缓存的过期时间,单位是毫秒。

     按F5键运行程序,此时再刷新页面,发现当前的时间已经不再变化,因为整个页的数据被缓存了起来。

    此时修改数据库的内容,然后刷新运行着的页面,可以发现,数据跟着发生了变化。这就是数据库缓存依赖的体现。当数据库内容更新时,不管缓存的时间有没有到,缓存的内容都会被更新。

16.5  Session和Cache的区别

以前实现数据的缓存有很多种方法,有客户端的Cookie,有服务器端的Session和Application。其中Cookie是保存在客户端的一组数据,主要用来保存用户名等个人信息。Session则保存对话信息。Application则是保存在整个应用程序范围内的信息,相当于全局变量。通常使用最频繁的是Session,那么Session和Cache又有什么区别呢?

本节结合使用经验,详细介绍Session缓存和Cache缓存的区别。

(1)最大的区别是Cache提供缓存依赖来更新数据,而Session只能依靠定义的缓存时间来判断缓存数据是否有效。

(2)即使应用程序终止,只要Cache.Add方法中定义的缓存时间未过期,下次开启应用程序时,缓存的数据依然存在。而Session缓存只是存在于一次会话中,会话结束后,数据也就失效了。

(3)Session容易丢失,导致数据的不确定性,而Cache不会出现这种情况。

(4)由于Session是每次会话就被加载,所以不适宜存放大量信息,否则会导致服务器的性能降低。而Cache则主要用来保存大容量信息,如数据库中的多个表。

(5)VS2005的测试版提供了将缓存保存在硬盘上的参数,但正式版中取消了这个功能,估计其在以后版本中会重新实现。而Session目前只能保存在内存中,对其性能有影响。

为了提高Cache的有效利用率,建议对于不经常改动的数据使用Cache。

16.6  小结

本章主要介绍了如何使用System.Web.Caching命名空间下的类,主要包括以下三个:Cache, CacheDependency和SqlCacheDependency。Cache类主要用来创建缓存项,主要针对的是数据不经常改变,但又使用频繁的数据表或文件。另两个类是.NET 2.0新添加的缓存依赖服务。通过文件依赖或数据库依赖,可以实现缓存数据的及时更新。

通过本章的学习,希望可以提高读者编写的网站的数据读取速度,节约带宽,为Web 2.0时代的到来打下坚实的基础。

 

出处:《C#实用开发参考大全》一书第16章。
参考: http://www.cnblogs.com/codecrazy/archive/2010/10/14/1851936.html

不怕范围太大,大可以写上[^>]*)\1\s+>

转载于:https://www.cnblogs.com/mq0036/p/4031223.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259847.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神武4手游服务器维护,神武4手游势不可挡开服时间表_神武4手游新区开服预告_第一手游网手游开服表...

2020-06-1910:00新服天涯刀客已经开服2020-06-0510:00新服飞仙摘星已经开服2020-05-2910:00新服踏雪无痕已经开服2020-05-2210:00新服因缘际会已经开服2020-05-1910:00新服龙的传人已经开服2020-05-1510:00新服鸾凤和鸣已经开服2020-05-1211:40新服其疾如风已经开服2020-05-081…

BZOJ 4066 简单题 ——KD-Tree套替罪羊树

【题目分析】 直接x,y二维轮番划分&#xff0c;暴力即可。 套上替罪羊&#xff0c;打碎重构&#xff0c;对于时间复杂度有了保证。 写起来好麻烦&#xff0c;重构的技巧很棒&#xff01; 【代码】 #include <cstdio> #include <cstring> #include <iostream>…

【HTML5初探之绘制图像(上)】看我canvas元素引领下一代web页面

弧度一块可能有误&#xff0c;需要再研究 导航 【初探HTML5之使用新标签布局】用html5布局我的博客页&#xff01; 【HTML5初探之form标签】解放表单验证、增加文件上传、集成拖放 【HTML5初探之绘制图像&#xff08;上&#xff09;】看我canvas元素引领下一代web页面 【HTML5初…

或运算

逻辑或 ||int i, j, k;i 0x15;j 0x41;k i || j;反汇编代码如下:MOV DWORD PTR SS:[EBP-4], 15MOV DWORD PTR SS:[EBP-C], 41CMP DWORD PTR SS:[EBP-4], 0JNZ SHORT asm_OR.00401029CMP DWORD PTR SS:[EBP-C], 0JNZ SHORT asm_OR.00401029MOV DWORD PTR SS:[EBP-10], 0JMP SH…

构造方法的调用顺序和成员变量的初始化时机以及动态绑定

构造方法的调用顺序&#xff1a;子类构造器中&#xff0c;JVM会自动的先调用父类的构造方法&#xff0c;然后再执行子类构造方法。在JVM自动调用父类构造方法的时候&#xff0c;会完成父类中拥有的成员变量的值的初始化操作&#xff0c;此时子类的成员变量并未初始化&#xff0…

Python interview_python

https://github.com/taizilongxu/interview_python 1 Python的函数参数传递 strings, tuples, 和numbers是不可更改的对象&#xff0c;而list,dict等则是可以修改的对象 2 Python中的元类(metaclass) 3 staticmethod和classmethod python 三个方法&#xff0c;静态方法&#xf…

突然不能 ip访问服务器文件夹,用友U8 工作站连接不到服务器,ping IP及服务器名都正常,访问服务器共享文件夹也正常...

用友U8 U8存货采购入库单存货现存量与存货核算中的明细帐数量不符用友U8 U8存货采购入库单存货现存量与存货核算中的明细帐数量不符问题原因:错误原因见下面解决方案中的分析。解决方法:在查询存货明细帐和现存量09仓库存货510241数量为123&#xff0c;但在添采购入库单红字时却…

rocketmq 消息 自定义_RocketMQ消息轨迹-设计篇

RocketMQ 消息轨迹主要包含两篇文章&#xff1a;设计篇与源码分析篇&#xff0c;本节将详细介绍RocketMQ消息轨迹-设计相关。RocketMQ消息轨迹&#xff0c;主要跟踪消息发送、消息消费的轨迹&#xff0c;即详细记录消息各个处理环节的日志&#xff0c;从设计上至少需要解决如下…

再次献给那些心软的人!!!

上次那篇日志朋友看了评论说&#xff1a;别太悲观……为那些坏人成为坏人才是最不值得的&#xff01;而且好人说要当坏人就只是说说而已&#xff0c;真碰到啥事&#xff0c;依旧会傻傻的帮……没错&#xff0c;我还是傻傻的帮了&#xff0c;最初会表现出一点不乐意&#xff0c;…

手机做服务器性能咋样,服务器性能不足 怎样才能逼出最强状态

而且&#xff0c;服务器的节能不仅仅意味着节省了电费&#xff0c;其后续的散热降温等工作都可以得到更好的节约。同时&#xff0c;服务器的在长时间工作的情况下&#xff0c;保持较低温度有利于降低其承载负荷&#xff0c;最大限度发挥其能力&#xff0c;保障服务器工作运行的…

ASP.NET跨页面传值技巧总结

1. 使用QueryString变量 QueryString是一种非常简单的传值方式&#xff0c;他可以将传送的值显示在浏览器的地址栏中。如果是传递一个或多个安全性要求不高或是结构简单的数值时&#xff0c;可以使用这个方法。但是对于传递数组或对象的话&#xff0c;就不能用这个方法了。下面…

RTMP协议中文翻译(首发)(转)

Adobe公司的实时消息传输协议 摘要 此备忘录描述了 Adobe公司的实时消息传输协议(RTMP)&#xff0c;此协议从属于应用层&#xff0c;被设计用来在适合的传输协议&#xff08;如TCP&#xff09;上复用和打包多媒体传输流&#xff08;如音频、视频和互动内容&#xff09;。 目录 …

关卡 动画 蓝图 运行_UE4入门之路(基础蓝图篇):蓝图的制作

蓝图系统简介蓝图系统是UE4中十分有代表性的一个特点&#xff0c;所谓蓝图就是一种可视化的脚本。该系统非常灵活且非常强大&#xff0c;因为它为设计人员提供了一般仅供程序员使用的所有概念及工具。 程序员能够很方便的创建一个基础系统&#xff0c;并交给策划进一步在蓝图中…

overfitting(过度拟合)的概念

来自&#xff1a;http://blog.csdn.net/fengzhe0411/article/details/7165549 最近几天在看模式识别方面的资料&#xff0c;多次遇到“overfitting”这个概念&#xff0c;最终觉得以下解释比较容易接受&#xff0c;就拿出来分享下。 overfittingt是这样一种现象&#xff1a;一个…

虚拟串口服务器zenetmanager,Avocent服务器/串口管理 KVM

MergePoint Unity交换机在单个设备中结合了 KVM over IP和串行控制台管理技术。这项独特的结合为IT管理员提供了用于访问和控制服务器、网络设备及其他数据中心和分支办公室设备的完整远程管理解决方案。MergePoint Unity交换机直接与物理KVM、USB和串行端口进行安全的远程带外…

KAFKA分布式消息系统

Kafka[1]是linkedin用于日志处理的分布式消息队列&#xff0c;linkedin的日志数据容量大&#xff0c;但对可靠性要求不高&#xff0c;其日志数据主要包括用户行为&#xff08;登录、浏览、点击、分享、喜欢&#xff09;以及系统运行日志&#xff08;CPU、内存、磁盘、网络、系统…

jar打包 剔除第三方依赖以及它的依赖_面试官:为什么Spring Boot的jar可以直接运行?...

来源&#xff1a;Gormats Notesfangjian0423.github.io/2017/05/31/springboot-executable-jar/Spring Boot Loader抽象的一些类JarLauncher的执行过程关于自定义的类加载器LaunchedURLClassLoaderSpring Boot Loader的作用SpringBoot提供了一个插件spring-boot-maven-plugin用…

CQRS架构图

2019独角兽企业重金招聘Python工程师标准>>> 转载于:https://my.oschina.net/darkness/blog/814243

SQLite中不支持的sql语法

今天很自然的在写Sql语句的时候用了Top&#xff0c;一开始没发现问题&#xff0c;因为我从数据库读出的值正好是0&#xff0c;而我习惯变量定义的时候也都赋值0&#xff0c;可是到我不要0的时候我就发现问题了。后来才知道&#xff0c;可爱的小sqlite竟然有不支持的sql语法。 看…

Analyzer普通用户登录不了[从网络访问此计算机]

问题&#xff1a; 最近客户诺奇反映说Analyzer普通用户登录不了&#xff0c;但是发现管理员又可以登录&#xff0c;几经周折发现原来是系统的本地安全策略设置了不让远程使用本地账户密码登录系统导致。解决方案&#xff1a; 修改本地安全策略的“从远程访问此计算机”中的用户…