ASP.NET 2.0 中使用自定义缓存依赖

asp.net|缓存

  在 ASP.NET 1.x 中,我们可以使用 CacheDependency 来实现缓存依赖策略,但由于这个类是 sealed 的,我们无法继承这个类来实现我们自己的策略。但是到了 ASP.NET 2.0,我们已经可以从这个类派生出自己的缓存依赖类了。

  假定我们要设计一个页面,需要从博客园首页获取最新的贴子信息。为了提高性能,我们希望页面数据仅当博客园首页有更新时才重新生成,否则的话就直接从缓存中获取。如何实现?

  一、设计 BlogCacheDependency 类

  先分析一下,首先,毫无疑问的,这个类应当从 CacheDependency 派生出来,然后它才能在 Cache 的 Insert 方法中使用,或者被用在 AggregateDependency 类中。

  其次,从博客园提供的 RSS 以及页面设计的角度考虑,可以在缓存中放置 RSS 数据,显示的时候使用一个样式转换。而在检查依赖性的时候,我们只需要简单地比较一下当前的 RSS 与网站的 RSS 是否相同就可以了。

  一个比较重要的问题是:我们何时去检查比较 RSS 数据?在每次请求的时候吗?显然不行,这样一来跟不使用缓存几乎没什么区别,甚至实际上加重了无谓的负担。考虑在没有请求的时候进行检查呢?我们可以使用一个 Timer 来控制,让它定期去检查一个是否有更新,如果有更新则通知依赖发生了改变。

  我们知道 CacheDependency 类有一个 HasChanged 属性,但是当 BlogCacheDependency 检查到依赖改变时如何告诉它的基类呢?这就是在 ASP.NET 2.0 中 CacheDependency 类中新增的 NotifyDependencyChanged 方法的使命了。

  此外为了便于重用,BlogCacheDependency 类须得有一个 feed 数据,用来保存我们要获取的 RSS 数据的 URL。还要有一个时间间隔,便于在使用的时候调整刷新速度。

  好,看看实际的实现代码:

 1 public class BlogCacheDependency : CacheDependency
 2 {
 3    private Timer _tickTimer;
 4    private int _timeInterval;
 5    private XPathNavigator _rss;
 6    private string _feed;
 7
 8    public XPathNavigator RSS
 9    {
10        get
11        {
12            return _rss;
13        }
14    }
15
16    public BlogCacheDependency(string feed, int timeInterval)
17    {
18        _feed = feed;
19        _timeInterval = timeInterval;
20        _rss = GetRSS();
21        _tickTimer = new Timer(new TimerCallback(CheckDependencyCallback),
22            this, _timeInterval * 1000, _timeInterval * 1000);
23    }
24
25    private XPathNavigator GetRSS()
26    {
27        XPathDocument rssDoc = new XPathDocument(_feed);
28        return rssDoc.CreateNavigator();
29    }
30
31    public void CheckDependencyCallback(object sender)
32    {
33        BlogCacheDependency bcd = sender as BlogCacheDependency;
34        XPathNavigator newRSS = GetRSS();
35        if (newRSS.OuterXml != _rss.OuterXml)
36        {
37            bcd.NotifyDependencyChanged(bcd, EventArgs.Empty);
38        }
39    }
40
41    protected override void DependencyDispose()
42    {
43        _tickTimer = null;
44        base.DependencyDispose();
45    }
46}
47
48

  这里,BlogCacheDependency 的构造函数中使用 _tickTimer 实现了一个定时检查更新的机制,它根据设定的时间间隔去调用 CheckDependencyCallback 方法。

  而 CheckDependencyCallback 方法则将两个 RSS 信息进行比较,如果不同,则调用 NotifyDependencyChanged 方法通知基类,相应的缓存依赖已经发生了变化,缓存中的数据应当被清除。

  二、页面设计

  下面是页面代码(有删节),其中显示了 BlogCacheDependency 的使用方法:

 1<script runat="server">   
 2    protected void Page_Load(object sender, EventArgs e)
 3    {
 4        string feed = "http://www.cnblogs.com/RSS.aspx";
 5        if (Cache[feed] == null)
 6        {
 7            BlogCacheDependency bcd = new BlogCacheDependency(feed, 600);
 8            Cache.Insert(feed, bcd.RSS, bcd);
 9            Label1.Text = "当前数据为刚刚获取,并已更新入缓存!";
10        }
11        else
12        {
13            Label1.Text = "当前数据系从缓存中取得!";
14        }  
15        RssXml.XPathNavigator = Cache[feed] as System.Xml.XPath.XPathNavigator;
16        RssXml.TransformSource = "translate.xsl";
17    }
18</script>
19
20<body>
21    <form id="form1" runat="server">
22       博客园最新贴子:
23       <br />
24       <asp:Xml ID="RssXml" runat="server" />
25       <br />
26       <asp:Label ID="Label1" runat="server" ForeColor="red" />
27 </form>
28</body>
29

  本例中设定的访问博客园首页最新贴子列表,时间间隔为600秒,即每10分钟检查一次更新情况。

  几个值得注意的地方:

  1、注意使用的 RssXml.XPathNavigator 属性,有人可能奇怪为什么不用 RssXml.Document 呢?实际上 Document 属性在 .NET 2.0 中已废除,推荐用来替代的是 XPathNavigator 属性,从前面的 BlogCacheDependency 类中可以看到,它是来源于 XPathDocument.CreateNavigator() 所创建的,从 MSDN 我们可以知道,XPathDocument 类提供一种只读的快速缓存,显然就这个例子而言确实更加适合。

  2、考虑一下,BlogCacheDependency 类中的 DependencyDispose 方法作何用?它与 Dispose 方法有何区别?让我们想一想,如果说某一次检查更新时,已经发现依赖变化了,但是却一直没有再次发送请求,那么这时会不会始终连续不断按间隔地执行 CheckDependencyCallback 方法呢?如果真的如此的话,那岂不是完全多余,因为只要查到一次有变化就不必再查了嘛。而如果我们进行跟踪或是记录日志的话可以发现,实际上只要查到依赖变化以后就不会再次 Check 了。奥妙在哪里?想一想就能知道 NotifyDependencyChanged 方法大有玄机,而且之所以会有 DependencyDispose 方法的原因其实也就在这里。其中的设计思想,值得我们细细品味吧。

  三、页面使用到的 translate.xsl

  不再多说,贴出主要代码:

 1<xsl:template match="channel">
 2 <div>
 3  <xsl:for-each select="item">
 4   <a>
 5    <xsl:attribute name="href">
 6     <xsl:value-of select="link"/>
 7    </xsl:attribute>
 8    <xsl:value-of select="title"/>
 9   </a>
10   <br />   
11  </xsl:for-each>
12 </div>
13</xsl:template>

  四、执行情况

  这是最初执行的截图:

  当博客园首页没有出现新贴子的时候,我们刷新页面,总是可以得到如下的页面:

  而一旦有了新贴子,那么刷新的时候出现的是上一张图。

  五、你想再高级一点吗?

  如果你和我一样懒或是比我更懒,那么你可以考虑再用 javascript 写一个自动刷新页面的小功能,再把页面美工一下,或是包装成一个可复用的组件用在你的网站上,又或者只是想在本机里做一个“我最关注的内容集”之类的东西?嗯,想来效果会比较不错的哦。

时间: 2024-12-31 18:45:59

ASP.NET 2.0 中使用自定义缓存依赖的相关文章

ASP.NET 2.0 中改进的缓存功能

asp.net|缓存 Stephen Walther      Microsoft Corporation      适用于:      Microsoft ASP.NET 2.0      Microsoft ASP.NET Framework      Microsoft SQL Server      Microsoft Visual Studio .NET      摘要:本文中,Stephen Walther 将重点介绍 ASP.NET 2.0 中新增的缓存功能,以及如何使用这些新功能

ASP.NET 2.0中使用自定义provider

在ASP.NET 2.0中,新增加的membership provider功能,以及结合功能强大 的一系列注册,登陆控件,可以很方便地对用户的登陆和权限等进行管理(参见 <<ASP.NET 2.0登陆控件简介>>). 但是,可能大家会发现,ASP.NET 2.0自带的这些登陆控件和membership的管 理功能,默认的是和sql server 2005 express搭配使用的,那么,如何改成使 用SQL Server 2000或者是其他的数据源,如access,oracle等呢

ASP.NET 2.0中的页面输出缓存

asp.net|缓存|页面 静态页面全部内容保存在服务器内存中.当再有请求时,系统将缓存中的相关数据直接输出,直到缓存数据过期.这个过程中,缓存不需要再次经过页面处理生命周期.这样可以缩短请求响应时间,提高应用程序性能.很显然,页面输出缓存适用于不需要频繁更新数据,而占用大量时间和资源才能编译生成的页面.对于那些数据经常更新的页面,则不适用.默认情况下,ASP.NET 2.0启用了页面输出缓存功能,但并不缓存任何响应的输出.开发人员必须通过设置,使得某些页面的响应成为缓存的一部分. 设置页面输出

ASP.NET 2.0中的页面输出缓存_实用技巧

静态页面全部内容保存在服务器内存中.当再有请求时,系统将缓存中的相关数据直接输出,直到缓存数据过期.这个过程中,缓存不需要再次经过页面处理生命周期.这样可以缩短请求响应时间,提高应用程序性能.很显然,页面输出缓存适用于不需要频繁更新数据,而占用大量时间和资源才能编译生成的页面.对于那些数据经常更新的页面,则不适用.默认情况下,ASP.NET 2.0启用了页面输出缓存功能,但并不缓存任何响应的输出.开发人员必须通过设置,使得某些页面的响应成为缓存的一部分. 设置页面输出缓存可以使用以下两种方式:一

理解并扩展 ASP.NET 2.0 中的站点导航系统

asp.net|导航|站点 摘要:ASP.NET 2.0 站点导航系统构建于一个功能强大.灵活的体系结构之上,设计这样的体系结构是为了使其具有可扩展性.本文探究站点提供程序的体系结构并提供一个示例提供程序,该提供程序将文件系统公开为站点导航的数据源,从而替代了标准的 Web.sitemap XML 文件. 简介 大多数 web 站点采用可视化导航的某种形式来帮助用户轻松地浏览站点,以及查找他们所需的信息和 Web 页.尽管不同站点之间的感观效果千差万别,但是通常会使用相同的基本元素 - 以导航栏

ASP.NET 2.0 中的异步页功能应用

asp.net|异步 下载本文源代码:WickedCode0510.exe ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用

ASP.NET 2.0 中的SqlCacheDependency特性

asp.net|cache ASP.NET中的Page Cache是个很有用的东东,只要简单的在页面上方加上一个OutputCache标签,就可以让页面在制定的Duration内直接把自动保存在缓存中的页面内容输出,而不需要让ASP.NET引擎再次执行页面代码,当然,节省这点执行时间并不是最主要的理由,主要理由是如果页面内容是从数据库中取出,那么就可以省去连接数据库.取数据的步骤,这个好处可大了.       PageCache有点小小的问题,比如,很多ASP.NET论坛的首页就用了PageCa

在ASP.NET 2.0中实现数据的绑定

ASP.NET的第一个版本就已经建立了一组新的数据库绑定控件.有了这些控件 的支持,数据的可视化和编辑就简单多了,其中一个最重要的控件就是DataGrid 控件.但是这个控件也有很多缺点.它为数据的排序,分页和编辑提供了一些内 置的功能,但必须手动实现. 而ASP.NET 2.0中采用了一种新的方式来解决以前版本的诸多问题, 并且提供了标准的功能.现在可以对任何数据源进行排序,分页和编辑----在大 多数情况下不需要输入任何代码.由于几乎所有的动态WEB程序都要考虑到与数据库的交互,幸运的是在A

ASP.NET 2.0 中的异步页[来自MSDN]

ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求的线程在调用返回之前处于挂起状态.这影响了可伸缩性,