15.4 应用程序数据缓存
知识点讲解:光盘:视频\PPT讲解(知识点)\第15章\应用程序数据缓存.mp4
应用程序数据缓存的主要功能是在内存中存储各种与应用程序相关的对象,它主要由Cache类实现。该类从属于System.Web.Caching命名空间,其实例对象为每个应用程序所专用。通过对Cache类的应用,可轻松实现添加、检索和移除应用程序数据缓存,以及移除缓存项时通知应用程序等功能。
Cache类提供了强大的功能,允许自定义一个缓存项并设置缓存的时间。例如,当缺乏系统内存时,缓存会自动移除很少使用的或优先级较低的项以释放内存。该技术也称为清理,这是缓存确保过期数据不使用宝贵的服务器资源的方式之一。
当执行清理操作时,可以设置Cache 给予某些项比其他项更高的优先级。若要指示项的重要性,可以在使用 Add或Insert方法添加项时指定一个CacheItemPriority枚举值。
当使用Add或Insert方法将项添加到缓存时,可以建立项的过期策略。也可以通过使用DateTime值指定项的确切过期时间(绝对过期时间)定义项的生存期。还可以使用TimeSpan值指定一个弹性过期时间,弹性过期时间允许用户根据项的上次访问时间来指定该项过期之前的运行时间。一旦项过期,便将它从缓存中移除。试图检索它的值的行为将返回Null,除非该项被重新添加到缓存中。
对于存储在缓存中的易失项(例如那些定期进行数据刷新的项或那些只在一段时间内有效的项),通常设置一种过期策略:只要这些项的数据保持为最新,就将它们保留在缓存中。例如,如果正在编写一个应用程序,该应用程序通过从另一个网站获取数据来跟踪体育比赛的比分,那么只要源网站上比赛的比分不更改,就可以缓存这些比分。在此情况下,可以根据其他网站更新比分的频率来设置过期策略。可以编写代码来确定缓存中是否是最新的比分。如果该比分不是最新的,则代码可以从源网站读取比分并缓存新值。
ASP.NET还允许用户根据外部文件、目录(文件依赖项)或另一个缓存项(键依赖项)来定义缓存项的有效性。如果具有关联依赖项的项发生更改,缓存项便会失效并从缓存中移除。可以使用该技术在项的数据源更改时从缓存中移除这些项。例如,如果编写一个处理XML文件中财务数据的应用程序,则可以从该文件将数据插入缓存中并在此XML文件上保留一个依赖项。当该文件更新时,从缓存中移除该项,应用程序重新读取XML文件,然后将刷新后的数据存入缓存中。
15.4.1 将项添加到缓存中
可以使用Cache对象访问应用程序缓存中的项,也可以使用Cache对象的Insert方法向应用程序缓存添加项。该方法向缓存添加项,并且通过几次重载,用户可以使用不同选项添加项,以设置依赖项、过期和移除通知。如果使用Insert方法向缓存添加项,并且已经存在与现有项同名的项,则缓存中的现有项将被替换。
还可以使用Add方法向缓存添加项。使用此方法,可以设置与 Insert 方法相同的所有选项;然而Add方法将返回用户添加到缓存中的对象。另外,如果使用Add方法,并且缓存中已经存在与现有项同名的项,则该方法不会替换该项,并且不会引发异常。
向应用程序缓存中添加项的方式有如下6种。
- 通过指定项的键和值,向缓存添加项。
- 使用 Insert 方法向缓存添加项。
- 向缓存添加项并添加依赖项,以便当该依赖项更改时,将该项从缓存中移除。可以基于其他缓存项、文件和多个对象设置依赖项。
- 将设有过期策略的项添加到缓存中。除了能设置项的依赖项以外,还可以设置项在一段时间以后(弹性过期)或在指定时间(绝对过期)过期。可以定义绝对过期时间或弹性过期时间,但不能同时定义两者。
- 向缓存添加项,并定义缓存的项的相对优先级。相对优先级帮助 .NET Framework 确定要移除的缓存项;较低优先级的项比较高优先级的项先从缓存中移除。
- 通过调用 Add 方法添加项。
除了这里介绍的依赖项,还可以在SQL Server表上或基于自定义依赖项创建依赖项。当从缓存中移除项时,还可以使用CacheItemRemovedCallback委托让应用程序缓存通知应用程序。
1.通过指定项的键和值向缓存添加项
通过指定项的键和值,像将项添加到字典中一样将其添加到缓存中。例如,在下面的代码中,将名为CacheItem1的项添加到Cache对象中。
Cache["CacheItem1"] = "Cached Item 1";
2.通过使用 Insert 方法将项添加到缓存中
Cache.Insert方法有4种重载方式,下面用示例代码的方式来说明Insert方法。
重载方式1的语法格式如下。
public void Insert (string key, Object value)
向 Cache 对象插入项,该项带有一个缓存键引用其位置,并使用 CacheItemPriority 枚举提供的默认值。其中,参数key用于引用该项的缓存键;参数value表示要插入缓存中的对象。例如下面的代码。
Cache.Insert("DSN", connectionString);
重载方式2的语法格式如下。
public void Insert (string key, Object value, CacheDependency dependencies)
上述语法格式用于向 Cache 中插入具有文件依赖项或键依赖项的对象。其中,参数key用于标识该项的缓存键;参数value表示要插入缓存中的对象;参数dependencies表示所插入对象的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数包含空引用。例如下面的代码。
Cache.Insert("DSN", connectionString,
new CacheDependency(Server.MapPath("myconfig.xml")));
重载方式3的语法格式如下。
public void Insert (string key, Object value, CacheDependency dependencies,
DateTime absoluteExpiration,TimeSpan slidingExpiration)
上述语法格式用于向 Cache 中插入具有依赖项和过期策略的对象,各个参数的具体说明如下。
- key:用于引用该对象的缓存键。
- value:要插入缓存中的对象。
- dependencies:所插入对象的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数包含空引用。
- absoluteExpiration:所插入对象将过期并从缓存中移除的时间。如果使用绝对过期,则 slidingExpiration 参数必须为NoSlidingExpiration。
- slidingExpiration:最后一次访问所插入对象时与该对象过期时之间的时间间隔。如果该值等效于 20 分钟,则对象在最后一次被访问的20分钟之后将过期并从缓存中移除。如果使用可调过期,则absoluteExpiration参数必须为NoAbsoluteExpiration。
例如下面的代码:
Cache.Insert("DSN", connectionString, null, DateTime.Now.AddMinutes(2), TimeSpan.Zero);
重载方式4的语法格式如下。
public void Insert (string key, Object value, CacheDependency dependencies,
DateTime absoluteExpiration,TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback)
上述语法格式用于向Cache对象中插入对象,后者具有依赖项、过期和优先级策略以及一个委托(可用于在从Cache移除插入项时通知应用程序)。各个参数的具体说明如下。
- key:用于引用该对象的缓存键。
- value:要插入缓存中的对象。
- dependencies:该项的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数包含空引用。
- absoluteExpiration:所插入对象将过期并被从缓存中移除的时间。如果使用绝对过期,则slidingExpiration参数必须为 NoSlidingExpiration。
- slidingExpiration:最后一次访问所插入对象时与该对象过期时之间的时间间隔。如果该值等效于 20 分钟,则对象在最后一次被访问的20分钟之后将过期并从缓存中移除。如果使用可调过期,则absoluteExpiration 参数必须为NoAbsoluteExpiration。
- priority:该对象相对于缓存中存储的其他项的成本,由 CacheItemPriority 枚举表示。该值由缓存在退出对象时使用;具有较低成本的对象在具有较高成本的对象之前从缓存中移除。
- onRemoveCallback:在从缓存中移除对象时将调用的委托(如果提供)。当从缓存中删除应用程序的对象时,可使用它来通知应用程序。
例如下面的代码。
Cache.Insert("DSN", connectionString, null,
DateTime.Now.AddMinutes(2),
TimeSpan.Zero,
CacheItemPriority.High,
onRemove);
3.使用Add 方法向缓存添加项
使用Add方法向缓存添加项的格式如下。
public Object Add (string key, Object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback
)
上述语法格式中各个参数的具体说明如下。
- key:用于引用该项的缓存键。
- value:要添加到缓存的项。
- dependencies:该项的文件依赖项或缓存键依赖项。当任何依赖项更改时,该对象即无效,并从缓存中移除。如果没有依赖项,则此参数包含空引用。
- absoluteExpiration:所添加对象将过期并从缓存中移除的时间。如果使用可调过期,则absoluteExpiration参数必须为NoAbsoluteExpiration。
- slidingExpiration:最后一次访问所添加对象时与该对象过期时之间的时间间隔。如果该值等效于20分钟,则对象在最后一次被访问的20分钟之后将过期并从缓存中移除。如果使用绝对过期,则slidingExpiration 参数必须为NoSlidingExpiration。
- priority:对象的相对成本,由CacheItemPriority枚举表示。缓存在退出对象时使用该值;具有较低成本的对象在具有较高成本的对象之前从缓存中移除。
- onRemoveCallback:在从缓存中移除对象时所调用的委托(如果提供)。当从缓存中删除应用程序的对象时,可使用它来通知应用程序。
注意:Insert方法的返回值为空,Add方法返回缓存项的数据对象;Insert方法有4个重载方法,较灵活;如果缓存中已经存在与现有项同名的项,Insert方法替换该项,而Add方法不会替换该项,并且不会引发异常。
15.4.2 检索缓存项的值
要从缓存中检索数据,应指定存储缓存项的键。不过,由于缓存中所存储的信息为易失信息,即该信息可能由ASP.NET移除,因此建议的开发模式是首先确定该项是否在缓存中。如果不在,则应将它重新添加到缓存中,然后检索该项。
1.检索缓存项的值
通过在 Cache 对象中进行检查来确定该项是否不为Null(在 Visual Basic 中为 Nothing)。如果该项存在,则将它分配给变量;否则,重新创建该项,并将它添加到缓存中,然后访问它。
例如,在下面代码中,将从缓存中检索名为“CacheItem”的项。
string cachedString;
cachedString = (string)Cache["CacheItem"];
if (cachedString == null)
{
cachedString = "你好!";
Cache.Insert("CacheItem", cachedString);
}
在上述代码中,将该项的内容分配给名为“cachedString”的变量。如果该项不在缓存中,则代码会将它添加到缓存中,然后将它分配给cachedString。
2.用Get方法检索指定项
Get方法的具体使用格式如下。
public Object Get (string key)
其中,参数key设置要检索的缓存项的标识符,其返回值是检索到的缓存项,未找到该键时为空引用。
例如下面的代码。
Cache.Get("MyTextBox.Value");
3.使用GetEnumerator方法检索指定项
GetEnumerator方法的功能是检索用于循环访问包含在缓存中的键设置及其值的字典枚举数。具体使用格式如下。
public IDictionaryEnumerator GetEnumerator ()
它的返回值是要循环访问 Cache 对象的枚举数。此方法枚举所有项的同时,可以将项添加到缓存或从缓存中移除项。
例如,在下面的代码中,使用GetEnumerator方法创建一个IDictionaryEnumerator对象 CacheEnum。
IDictionaryEnumerator CacheEnum = Cache.GetEnumerator();
while (CacheEnum.MoveNext())
{
cacheItem = Server.HtmlEncode(CacheEnum.Current.ToString());
Response.Write(cacheItem);
}
在上述代码中,枚举数在整个缓存中运行一遍,将各缓存项的值转换成字符串,然后将这些值写入“Web 窗体”页。
15.4.3 从缓存中移除项时通知应用程序
在大多数缓存方案中,当从缓存中移除项后,直到再次需要此项时,才需要将其放回缓存中。典型的开发模式是在使用项之前始终检查该项是否已在缓存中。如果项位于缓存中,则可以使用。如果不在缓存中,则应再次检索该项,然后将其添加回缓存。
但是,在某些情况下,如果从缓存中移除项时通知应用程序,可能非常有用。例如,用户可能有一个缓存的报告,创建该报告并进行处理需花费大量的时间。当该报告从缓存中移除时,用户希望重新生成该报告,并立即将其置于缓存中,以便下次请求该报告时,用户不必等待对此报告进行处理。
为了在从缓存中移除项时能够发出通知,ASP.NET提供了CacheItemRemovedCallback委托。该委托定义编写事件处理程序时使用的签名,当对从缓存中移除项进行响应时会调用此事件处理程序ASP.NET还提供CacheItemRemovedReason枚举,用于指定移除缓存项的原因。
通常,通过在管理尝试检索的特定缓存数据的业务对象中创建处理程序,以实现回调。例如,可能有一个ReportManager对象,该对象具有两种方法,即GetReport和CacheReport。GetReport方法检查缓存,以查看报告是否已缓存。如果没有,该方法将重新生成报告并将其缓存。CacheReport方法具有与CacheItemRemovedCallback委托相同的函数签名。从缓存中移除报告时,ASP.NET会调用CacheReport方法,然后将报告重新添加到缓存中。
从缓存中移除项时通知应用程序的操作过程如下。
(1)创建一个类,负责从缓存中检索项并处理回调方法,以将项添加回缓存中。
(2)在该类中,创建用于将项添加到缓存中的方法。
(3)在该类中,创建用于从缓存中获取项的方法。
(4)创建用于处理缓存项移除回调的方法。该方法必须具备与CacheItemRemovedCallback委托相同的函数签名。从缓存中删除项时,会在该方法中执行要运行的逻辑,如重新生成项并将其添加回缓存中。
测试缓存项回调的操作过程如下。
(1)创建一个 ASP.NET 网页,该网页将调用类中用于将项添加到缓存中的方法。
例如,在下面的代码中,通过调用ReportManager类的GetReport方法,在使用页面的Page_Load方法期间显示Label控件Label1中的报告。
protected void Page_Load(object sender, EventArgs e)
{
this.Label1.Text = ReportManager.GetReport();
}
(2)在浏览器中请求ASP.NET页并查看报告。
报告是在首次请求页时创建的,在缓存中的报告被移除之前,后续请求都将访问缓存中的报告。
实例075 实现应用程序数据缓存的各种应用
源码路径 光盘\daima\15\Web\ 视频路径 光盘\视频\实例\第15章\075
本实例的功能是通过页面中的操作按钮,实现应用程序数据缓存的各种应用。本实例的实现文件是chengxu.aspx,其主要实现代码如下。
<%@ Page Language="C#|" %>
<script language="C#|" runat="server">
//声明是什么原因造成的缓存移除的变量---注意类型
static CacheItemRemovedReason reason;
string[] tempArray ={ "北京", "上海", "广州", "成都", "深圳" };
//实现【增加】按钮的事件处理程序
protected void AddItemToCache(object sender, EventArgs e)
{
//如果缓存中的对象为空
if (Cache["tempArray"] == null)
{
//则创建缓存对象
//注意:这个增加方法的最后一个参数是一个委托,里面的方法是在下面定义的
//方法定义没有返回值,方法定义为: private void ItemRemoved(String Key,
// object value,CacheItemRemovedReason RemovedReason)
//以上这个方法就可以看出Add方法的委托的定义为:
//Deledete void CacheItemRemovedCallback(String Key,object value,
//CacheItemRemovedReason RemovedReason)
//所有程序在调用Add方法的时候也会自动触发委托里面的ItemRemoved方法
//下面是笔者自己写的方法
Cache.Add("tempArray", tempArray, null, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.Default, new
CacheItemRemovedCallback(ItemRemoved));
lbMessage.Text+=">>>>已经将字符串数组增加到缓存中.<br>";
}
else
{
lbMessage.Text+= ">>>>缓存中已经存在字符串数组了.<br>";
}
DisPlayCacheInfo();
}
//实现【检索】按钮的事件处理程序
private void GetItemFromCache(object sender, EventArgs e)
{
if (Cache["tempArray"] == null)
{
lbMessage.Text += ">>>>未索引到缓存,因为tempArray中缓存已被移除<br>";
}
else
{
lbMessage.Text += ">>>>以索引到缓存数组<br>";
}
DisPlayCacheInfo();
}
//实现【删除】按钮的事件处理程序
private void RemovedItemFromCache(object sender,EventArgs e)
{
if (Cache["tempArray"] == null)
{
lbMessage.Text += ">>>>未索引到缓存,因为tempArray中缓存已被移除<br>";
}
else
{
Cache.Remove("tempArray");
lbMessage.Text += "已经调用CacheItemRemovedCallback委托方法,缓存移除原因是:" +
reason.ToString() + "<br>";
lbMessage.Text += ">>>>已经删除数组中的数组缓存<br>";
}
DisPlayCacheInfo();
}
//CacheItemRemovedCallback的方法ItemRemoved定义
private void ItemRemoved(string Key,object value,CacheItemRemovedReason RemovedReason)
{
reason = RemovedReason;
}
private void DisPlayCacheInfo()
{
string CacheCount = Cache.Count.ToString();
lbCacheInfo.Text = "共包括" + CacheCount + "个缓存对象<br>";
IDictionaryEnumerator CacheEnum = Cache.GetEnumerator();
while (CacheEnum.MoveNext())
{
lbCacheInfo.Text += "索引到的Key为:" + CacheEnum.Key.ToString() +
"---" + "索引到的Value为:" + CacheEnum.Value.ToString();
}
}
</script>
……
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<fieldset style="width: 496px; height: 456px">
<legend>应用程序数据缓存的增删查</legend>
<br />
<div style="text-align:left; color:red">字符串数组内容如下:</div>
<div style="text-align:center">曼联,利物浦,切尔西,阿森纳,阿斯顿维拉</div>
<hr style="color:Navy" />
<div>
<center>
<asp:Button ID="btAdd" Text="增加" runat="server" OnClick="AddItemToCache" />
<asp:Button ID="btGet" Text="检索" runat="server" OnClick="GetItemFromCache" />
<asp:Button ID="btDel" Text="移除" runat="server" OnClick="RemovedItem FromCache" />
</center>
<center>
</center>
<center>
<div>
<asp:Label ID="lbCacheInfo" runat="server" ForeColor="RosyBrown" Width= "100%" Height="80px"></asp:Label>
</div>
</center>
</div>
<hr style="color:Navy" />
<asp:Label ID="lbMessage" runat="server" ForeColor="Blue" Height="50%" Width="100%"></asp:Label>
范例149:读取Excel中的数据
源码路径:光盘\演练范例\149视频路径:光盘\演练范例\149范例150:数据导入Excel时进行格式控制
源码路径:光盘\演练范例\150视频路径:光盘\演练范例\150\
上述代码执行后,将首先显示默认的控件元素界面,如图15-8所示;当分别单击【增加】、【检索】和【移除】按钮后,会执行对应的操作,并将操作结果显示在下方页面中,如图15-9所示。
图15-8 初始显示界面
图15-9 操作后界面效果
共有条评论 网友评论