缓存命名空间的讲解流程
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命名空间内的类组成
图16-2罗列的是在三层结构中缓存的部署情况。两个依赖类CacheDependency和sqlCache Dependency主要更改发生变化的缓存数据,起到通知的作用。当数据没有被缓存时,使用Cache类进行添加。
下面根据图16-2的部署,来介绍图中使用的缓存类。这些类的说明如表16-1所示。
图16-2 三层结构中缓存的部署图
表16-1 缓存命名空间中的类及其说明
16.2 管理缓存的类:Cache类
16.2.1 功能说明
Cache类属于字典类,其根据一定的规则存储用户需要的数据,这些数据的类型不受限制,可以是字符串、数组、数据表、Dataset和哈希表等。
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 方法详解
表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参数相关联。
下 面的代码演示了如何应用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.帮助");
Cache.Add("Category",myarray,null,DateTime.Now.AddSeconds(60),TimeSpan.Zero,CacheItemPriority.Normal,null);
myarray[1] = "2.交流园地"; //修改数组数据
string tmpStr = "这是一个临时数据";
Cache["tmpdata"] = tmpStr;
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方法移除缓存的临时数据
}
上述代码的运行结果如下:
这是一个临时数据
这是一个临时字符串
类型是数组这是一个临时字符串
System.Collections.ArrayList
其中在读取类型为ArrayList的数据时,由于没有进行类型转换,所以取出的是类型为“System.Collections.ArrayList”的对象。本书会在本节最后的实例中介绍如何读取数组的详细内容。
16.2.4 属性详解
Response.Write(Cache.Count);
Response.Write(Cache[“Category”].ToString());
本例的目的是将目录列表填充到下拉框中,当缓存失效后,目录列表的内容为空。演示的步骤如下所述。
在VS2005中创建一个网站,命名为“CacheSample”。
using System.Web.Caching;
using System.Collections;
protected void Page_Load(object sender,EventArgs e)
{
if (!Page.IsPostBack)
{
myarray.Add("古代历史");
myarray.Add("当代文学");
myarray.Add("流行小说");
myarray.Add("武侠小说");
if (Cache["Categorys"] == null) //判断是否存在缓存
{
//如果缓存不存在,则添加——保存时间是5秒
Cache.Add("Categorys",DateTime.Now.AddSeconds(5),
TimeSpan.Zero,null);
}
}
}
回到设计视图,双击按钮控件,切换到按钮的事件代码中。
protected void Button1_Click(object sender,EventArgs e)
{
if (Cache["Categorys"] != null) //判断缓存是否失效
{
//如果没有失效,则取出缓存的列表,注意类型的转换。
DropDownList1.DataSource = (ArrayList)Cache["Categorys"];
DropDownList1.DataBind();
}
else
{
DropDownList1.Items.Clear(); //如果已经失效,则清空列表
}
}
16.3 缓存依赖类:CacheDependency类
CacheDependency类是架设在Cache类和实际数据之间的桥梁。本节将详细介绍如何利用CacheDependency类实现数据缓存的及时更新。
16.3.1 功能说明
CacheDependency 类被称为是缓存依赖类,其具体意义表现在当缓存对象的实际数据发生改变时,它能及时通知缓存对象。例如缓存对象“Category”保存的是一个XML文 件的数据,如果XML文件发生了变化,那么系统通过CacheDependency类就会及时更新缓存对象“Category”的内容,这样就能保证用户 读取的永远是最新的数据。
16.3.2 语法定义
CacheDependency类的语法定义如下:
public class CacheDependency : IDisposable
//缓存依赖的文件路径
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",
new string[] { "Category","Category1" });
//关联依赖,还可以依赖于另一个文件缓存依赖
CacheDependency mydep5 = new CacheDependency(new string[] { "data.xml","Category1" },mydep);
CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml",DateTime.Now);
CacheDependency mydep6 = new CacheDependency(new string[] { "data.xml",
new string[] { "Category",mydep,DateTime.Now);
— 属性“HasChanged”:判断CacheDependency对象是否已更改。
16.3.4 典型应用:用CacheDependency获取最新的数据
本例主要演示如何使用CacheDependency类实现数据的及时更新。实例中使用一个GridView控件显示XML文件的数据,当XML文件的数据发生改变时,客户端可以及时更新。其实现的功能如图16-3所示。
演示的详细步骤如下所述。
打开VS2005,创建一个网站,命名为“CacheDependencySample”。
<?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>
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),
CacheItemPriority.Normal,null);
}
}
}
切换回设计视图,再双击按钮控件,此时光标停靠在按钮的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",
CacheItemPriority.Normal,null);
}
GridView1.DataSource = Cache["BOOKS"];
GridView1.DataBind();
}
注意:当XML文件发生改变后,其实缓存依赖和缓存项都被移除了,必须重新定义。
16.4.1 功能说明
16.4.2 语法定义
sqlCacheDependency类的使用语法如下:
public class sqlCacheDependency : IDisposable
public sqlCacheDependency(string database,string table)
— HasChanged:判断数据库缓存依赖是否发生了变化。
— Dispose:释放缓存依赖所占用的资源。
这三个成员的使用方法同CacheDependency类的成员相似,本节不再赘述。
在 下节要介绍的使用实例中,将不再使用代码的方式实现缓存依赖,而是使用“OutputCache”在.NET 2.0中提供的sqlCacheDependency参数实现数据库表的缓存。如果要使用编程的方式实现此功能,可参考CacheDependency类 的实例。
16.4.4 使用sqlCacheDependency类的操作流程
|
图16-6 使用数据库缓存依赖的流程
表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 CGJ-57F90CCA64C/sqlEXPRESS -U <Username> -P <Password> -ed -d testCache -et -t CacheTable
输入命令后,按回车键。如果执行成功,效果如图16-7所示。
打开VS2005,新建一个网站,命名为“sqlCacheDependency”。
<connectionStrings>
<add name="TestCacheConnectionString" connectionString="Data Source=CGJ-57F90 CCA64C/sqlexpress;Initial Catalog=testCache;Integrated Security=True" providerName= "System.
Data.sqlClient"/>
</connectionStrings>
<caching>
<sqlCacheDependency enabled = "true" pollTime = "1000" >
<databases>
<add name="testCache"
connectionStringName="TestCacheConnectionString"
pollTime = "1000" />
</databases>
</sqlCacheDependency>
</caching>
按Ctrl+S组合键保存配置文件的更改。
为GridView配置数据源。单击其任务列表,在“选择数据源”下拉框中,单击“新建数据源”命令,打开数据源的配置向导。
在打开的数据源类型窗口中,选择“数据库”,单击“确定”按钮,出现选择连接字符串窗口,通过下拉列表选择刚刚创建的“TestCacheConnectionString”连接串。
单击“下一步”按钮,出现“配置Select语句”对话框,在“列”列表框中选择“*”,表示选中所有列。
单击“下一步”按钮出现测试查询对话框,然后单击“完成”按钮。
Literal1.Text = DateTime.Now.ToString();
按Ctrl+S组合键保存当前页的设计,再按F5键运行程序。当刷新页面时,可以看到时间是不断变化的,这说明数据并没有来自缓存。
<%@ 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不会出现这种情况。
为了提高Cache的有效利用率,建议对于不经常改动的数据使用Cache。
16.6 小结
本章主要介绍了如何 使用System.Web.Caching命名空间下的类,主要包括以下三个:Cache,CacheDependency和sqlCacheDependency。Cache类主要用来创建缓存项,主要针对的是数据不经常改变,但又使用频繁的 数据表或文件。另两个类是.NET 2.0新添加的缓存依赖服务。通过文件依赖或数据库依赖,可以实现缓存数据的及时更新。
通过本章的学习,希望可以提高读者编写的网站的数据读取速度,节约带宽,为Web 2.0时代的到来打下坚实的基础。