In ASP.NET 1.x, we can use CacheDependency to implement cache dependency strategies, but since this class is sealed, we cannot inherit this class to implement our own strategies. But with ASP.NET 2.0, we can already derive our own cache dependency classes from this class.
Suppose we want to design a page and need to obtain the latest post information from the blog homepage. In order to improve performance, we hope that the page data will only be regenerated when the home page of the blog park is updated, otherwise it will be obtained directly from the cache. How to achieve?
1. Design the BlogCacheDependency class
and analyze it first. First of all, there is no doubt that this class should be derived from CacheDependency, and then it can be used in the Insert method of Cache, or used in the AggregateDependency class.
Secondly, from the perspective of RSS provided by Blog Park and page design, you can place RSS data in the cache and use a style conversion when displaying it. When checking dependencies, we only need to simply compare whether the current RSS is the same as the RSS of the website.
A more important question is: when do we check and compare RSS data? On every request? Obviously not. This is almost the same as not using cache, and it actually adds unnecessary burden. What about checking in without a request? We can use a Timer to control it and let it check whether there is an update regularly. If there is an update, it will notify the dependency of the change.
We know that the CacheDependency class has a HasChanged property, but how does BlogCacheDependency tell its base class when it detects a dependency change? This is the mission of the new NotifyDependencyChanged method in the CacheDependency class in ASP.NET 2.0.
In addition, in order to facilitate reuse, the BlogCacheDependency class must have a feed data to save the URL of the RSS data we want to obtain. There is also a time interval to facilitate adjusting the refresh speed during use.
OK, let’s take a look at the actual implementation code:
1public 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);
twenty three }
twenty four
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
Here, the constructor of BlogCacheDependency uses _tickTimer to implement a mechanism for regularly checking updates, which calls the CheckDependencyCallback method according to the set time interval.
The CheckDependencyCallback method compares the two RSS information. If they are different, the NotifyDependencyChanged method is called to notify the base class that the corresponding cache dependency has changed and the data in the cache should be cleared.
2. Page design
The following is the page code (abridged), which shows how to use 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 = "The current data has just been obtained and has been updated into the cache!";
10}
11 else
12 {
13 Label1.Text = "The current data is obtained from the cache!";
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 Blog Park latest posts:
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
In this example, the time interval set for accessing the latest posts list on the homepage of the blog park is 600 seconds, that is, the update status is checked every 10 minutes.
Several points worth noting:
1. Pay attention to the RssXml.XPathNavigator attribute used. Some people may wonder why RssXml.Document is not used? In fact, the Document attribute has been abolished in .NET 2.0. The recommended replacement is the XPathNavigator attribute. As you can see from the previous BlogCacheDependency class, it is created from XPathDocument.CreateNavigator(). From MSDN, we can know that, The XPathDocument class provides a read-only fast cache, which is obviously more suitable for this example.
2. Think about it, what is the purpose of the DependencyDispose method in the BlogCacheDependency class? How does it differ from the Dispose method? Let's think about it. If a dependency change has been found when checking for updates, but the request has not been sent again, will the CheckDependencyCallback method be executed continuously at intervals? If this is really the case, wouldn't it be completely redundant, because as long as a change is detected once, there is no need to check again. And if we track or record logs, we can find that in fact, as long as dependency changes are found, they will not be checked again. What's the secret? If you think about it, you will know that the NotifyDependencyChanged method has a lot of mystery, and the reason why there is a DependencyDispose method is actually here. The design ideas in it are worth savoring.
3. I won’t say more about the translate.xsl used on the page
, but here are the main codes:
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>
4. Execution:
This is a screenshot of the initial execution:
When no new posts appear on the homepage of the blog garden, we refresh the page and always get the following page:
Once there is a new post, the previous picture will appear when refreshing.
5. Do you want to be more advanced?
If you are as lazy as me or lazier than me, then you can consider using javascript to write a small function that automatically refreshes the page, and then decorate the page, or package it into a reusable component for use on your website Or do you just want to create something like a “content collection I care about most” in this machine? Well, I think the effect will be quite good.