Using the Cache Object

In addition to all the ways you've already seen to cache data for Web applications, ASP.NET supports yet another—the Cache object. Each Page object exposes a Cache object. Cached data is not specific to an individual user, page, or session; cached data belongs to the application. The cache, like the Application object, contains pairs of keys and values, but it also contains methods that let you determine exactly when and how long to cache the data, to specify the priority of those items (which ones the server recycles first if memory becomes scarce), and how long a cached item remains valid. You can also create dependencies between items in the Cache and another resource, such as a file or another cached item, so that changes to the dependent object let you refresh the cache.

For example, suppose your application uses an XSLT stylesheet that changes fairly frequently because of variations in advertisement size and placement. You could read the stylesheet from disk for every request, but that's much slower than reading the stylesheet from memory. However, if you cache the stylesheet, you need to be able to refresh it whenever the disk copy of the stylesheet file changes. You could write code to ensure that the file date and size have not changed since cacheing the copy in memory, but creating a file dependency between the cached copy of the XSLT and the disk file solves the problem without your having to write custom code. You can use a dependency between cached items as a "trigger" to ensure that the items stay synchronized.

You cache items by calling the Cache.Insert or Cache.Add method. Both methods let you specify the expiration time, refresh interval, and dependencies. The Add method requires the parameters shown in Table 17.1.

Table 17.1: The Cache Object's Add Method Parameters

Parameter Name

Description

Key

A string value used as the key for retrieving, refreshing, or removing an object from the

Cache.

Value

The object you want to place into the Cache.

Dependencies

A filename, a directory name, an array of files, or an array of cache keys. The CacheDependency monitors the items for changes. You can also create a CacheDependency object that depends on another CacheDependency object. Finally, you can specify when monitoring should begin.

For example, the Web Form cacheExample1.aspx (see Listing 17.6) caches the contents of a text file named items.txt and creates a dependency on the source file. If you change the source file, the cache updates automatically.

Listing 17.6: The Web Form CacheExamplel.aspx Creates a Cache Object with a File Dependency(cacheExamplel.aspx.cs)

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Web;

using System.Web.SessionState;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.IO;

using System.Web.Cacheing;

namespace CSharpASP.ch17 {

/// Summary description for cacheExamplel. /// </summary>

public class cacheExamplel : System.Web.UI.Page {

protected System.Web.UI.WebControls.Label Labell; protected System.Web.UI.WebControls.ListBox lstltems; private void Page Load(object sender, System.EventArgs e) {

String[] aList;

aList = (String[]) Cache.Get("items"); if (aList == null) {

Response.Write("Reading from file.<br>");

String aFilename = Server.MapPath(".") + "\\items.txt";

Filelnfo fi = new Filelnfo(aFilename);

StreamReader sr = null;

Cache.Add("items", aList, new CacheDependency(aFilename), DateTime.MaxValue, new TimeSpan(1, 1, 1), CacheltemPriority.Normal, new CacheltemRemovedCallback(removingltems));

Response.Write("Read from cache.");

lstItems.DataSource = aList; lstItems.DataBind();

private void removingItems(String key, Object value, CacheItemRemovedReason reason) {

Response.Write("Item has been removed from the cache.");

// autogenerated code not shown }

For this example, the item's text file itself can have any content in it as long as it's a carriage-return/linefeed delimited list—in other words, each item appears on a single line. I started with a file containing the following:

Item 1 Item 2 Item 3 Item 4 Item 5

When you run the Web Form, the code reads the items.txt file whenever the Cache item named "items" is null. That condition occurs the first time you run the Web Form, and—because of the file dependency—whenever the items.txt file changes. In that case, the code creates a string array object and stores the string array in the Cache object with a dependency on the text file (see Figure 17.3).

Figure 17.3: The Web Form cacheExample1.aspx displays the text Reading from file. whenever the cache is refreshed ra-p ,3? PI" U #'.VH

Figure 17.3: The Web Form cacheExample1.aspx displays the text Reading from file. whenever the cache is refreshed

Subsequent requests for the page display the data from the cache (see Figure 17.4).

Set the cacheExample1.aspx file as the start page for the application, and refresh the page so that you're sure the request reads the data from the cache. Now, without halting the application, open the items.txt file and make some changes. I added two extra items to the bottom of the file.

Item Item

Figure 17.4: The Web Form cacheExample1.aspx displays the text Read from cache. when the cache is current

After saving your changes to the items.txt file, refresh the page again. The change to the file forces the Cache to refresh the "items" object for the next request, so the code to read the text file executes again, and you'll see the added data in your browser (see Figure 17.5).

Figure 17.5: The Web Form cacheExample1.aspx displays the text Reading from file. after refreshing the cache

The Cache.Add and Cache.Insert methods are similar but not identical. First, the Add method returns the newly cached object, while the Insert method does not. Second, if an item with the specified key already exists in the Cache, the Insert method replaces it, but the Add method does not. The Web Form cacheExample2.aspx illustrates this second difference between the two methods (see Listing 17.7).

Both methods take the same parameters.

Listing 17.7: The Cache.Add and Insert Methods Perform Differently

(cacheExample2.aspx.cs)

private void Page Load(object sender, System.EventArgs e) { /*

* Uncomment the following code to see all the data

//Response.Write("Cache count before clearing is: " +

//Cache.Count + "<br>"); //Response.Write("<b>Cached items</b>:<br>"); //foreach(DictionaryEntry de in Cache) {

// Response.Write("Removing key:" + de.Key + "<br>"); // }

foreach(DictionaryEntry de in Cache) { Cache.Remove((String) de.Key);

Cache.Add("AddString", "Add1", null, DateTime.MaxValue, TimeSpan.FromMinutes(60),

System.Web.Cacheing.CacheItemPriority.Default,null); Cache.Add("AddString", "Add2", null, DateTime.MaxValue, TimeSpan.FromMinutes(60),

System.Web.Cacheing.CacheItemPriority.Default, null); Response.Write("Cache count after two Add methods=" +

Cache.Count + "<br>"); Response.Write("Cache item AddString=" + Cache.Get("AddString") + "<br>");

Cache.Insert("InsertString", "Insert1", null, DateTime.MaxValue, TimeSpan.FromMinutes(60), System.Web.Cacheing.CacheItemPriority.Default, null); Cache.Insert("InsertString", "Insert2", null, DateTime.MaxValue, TimeSpan.FromMinutes(60),

System.Web.Cacheing.CacheItemPriority.Default, null);

Response.Write("Cache count after two Insert methods=" +

Cache.Count + "<br>"); Response.Write("Cache item InsertString=" + Cache.Get("InsertString") + "<br>");

The output from the Add method call displays Add1, meaning that the second Add call did not replace the value—but it doesn't generate an error either, which means you must be very careful when using this method. In contrast, the output from the Insert method displays Insert2, meaning that it did replace the value.

Warning The Cache keys are case sensitive. For example, the keys myvalue and myValue are not identical and may refer to different objects. There's no option to change the case sensitivity of the keys, making it very easy to accidentally create additional keys.

The ASP.NET engine itself uses the Cache extensively. The reason for the clear Cache code in Listing17.7 is primarily to clear the Cache of all the system-generated values so that the example numbers make sense. To see how the system uses the Cache, uncomment the commented code in Listing 17.7 that appears before the loop that clears the Cache.

Note The following code exists on www.sybex.com but is commented out. Enable the code to see the output.

Response.Write("Cache count before clearing is: " & _

Cache.Count & "<Br>") Response.Write("<b>Cached items</b>:<br>") For Each de In Cache

Response.Write("Removing key: " & de.Key & "<br>") Next

' clear the cache For Each de In Cache

Cache.Remove(de.Key) Next

Note I generated this sample immediately after clearing the Cache object during the preceding request. If you run several other ASPX files before requesting this sample, you'll see that the system caches a lot of data in the Cache object. Knowing that the system relies on the Cache object should affect how you think about using the feature—in other words, it's extremely robust.

You're not limited to watching a single file for changes. You can create a list of files and use the entire list as a dependency. Thus, you can go far beyond this simple example using the Cache object. For example, you can cache database data based on a file dependency. By writing a trigger in your database that alters a file, your code can update the Cache. Because the Cache object has Application scope, you can cache objects on one page and use them as dependencies that, when changed, control other pages in your application. The sky's the limit. I'm certain you'll see innovative uses of the Cache object in the near future.

Was this article helpful?

0 0

Post a comment