Using the Cache APIs

only for RuBoard

Up to this point, you have only seen how to enable output caching. There is another side to caching, named data caching. This enables you to cache objects such as a DataSet or an ArrayList and share these objects application wide. For instance, say you have a DataSet that is created and used in more than one place in your application, yet it is always the same data. You can use data caching to place that DataSet into the cache the first time it is created and then access the DataSet from the cache when and where it's needed within your application. You can take it a step further by using page output caching on top of that.

In this section, I will give you samples of how to put data into the cache and how to access it. I'll also be discussing how to set expiration times, remove items from the cache, and how to work with file dependent data (ex: An XML file from which a DataSet is populated ). First, let's look at a simple example of inserting objects into the cache using the Cache.Insert method. Listing 16.14 contains an example that puts an ArrayList object and a DateTime object into the cache.

Listing 16.14 Putting an ArrayList and a DateTime Object into the Cache
 [VisualBasic.NET] 01: <script language="vb" runat="server"> 02: 03:  public sub Page_Load(sender as Object, e as EventArgs) 04: 05:   dim LocalTime as DateTime 06:   dim LocalArrayList as ArrayList 07: 08:    '***Check if LocalTime is nothing*** 09:   if Cache.Get("TimeCache") is nothing then 10: 11:    LocalTime = DateTime.Now 12:    Cache.Insert("TimeCache",LocalTime) 13:    lblCacheTime.Text = "<b>DateTime object put in the cache:</b>&nbsp;" & graphics/ccc.gif LocalTime.ToString("G") 14: 15:   else 16: 17:    LocalTime = CType(Cache.Get("TimeCache"), DateTime) 18:    lblCacheTime.Text = "<b>DateTime object from the cache:</b>&nbsp;" & graphics/ccc.gif LocalTime.ToString("G") 19: 20:   end if 21:   '***End*** 22: 23:   '***Check if LocalArrayList is nothing*** 24:   if Cache.Get("ArrayListCache") is nothing then 25: 26:    dim i as integer 27:    LocalArrayList= new ArrayList() 28:    for i = 0 to 10 29:     LocalArrayList.Add("Item - " & i) 30:    next i 31: 32:    Cache.Insert("ArrayListCache", LocalArrayList) 33:    ArrayListContents.DataSource = LocalArrayList 34:    ArrayListContents.DataBind() 35:    lblArrayListMessage.Text = "<b>ArrayList object put in the cache: </b>&nbsp;" 36: 37:   else 38: 39:    LocalArrayList = CType(Cache.Get("ArrayListCache"),ArrayList) 40:    ArrayListContents.DataSource = LocalArrayList 41:    ArrayListContents.DataBind() 42:    lblArrayListMessage.Text = "<b>ArrayList object from the cache: </b>&nbsp;" 43: 44:   end if 45:   '***End*** 46: 47:  end sub 48: </script> 49: [C#.NET  Replace server code] 01: <script language="c#" runat="server"> 02: 03:  void Page_Load(Object sender, EventArgs e) { 04: 05:   DateTime LocalTime; 06:   ArrayList LocalArrayList; 07: 08:   //'***Check if LocalTime is nothing*** 09:   if (Cache.Get("TimeCache") == null) { 10: 11:    LocalTime = DateTime.Now; 12:    Cache.Insert("TimeCache",LocalTime); 13:    lblCacheTime.Text = "<b>DateTime object put in the cache:</b>&nbsp;" + graphics/ccc.gif LocalTime.ToString("G"); 14: 15:   }  else { 16: 17:     LocalTime = (DateTime) Cache.Get("TimeCache"); 18:     lblCacheTime.Text = "<b>DateTime object from the cache:</b>&nbsp;" + graphics/ccc.gif LocalTime.ToString("G"); 19: 20:   } 21:   //'***End*** 22: 23:   //'***Check if LocalArrayList is nothing*** 24:   if (Cache.Get("ArrayListCache") == null) { 25: 26:    int i; 27:    LocalArrayList= new ArrayList(); 28:    for (i = 0; i < 11; i++) { 29:     LocalArrayList.Add("Item - " + i); 30:    } 31: 32:    Cache.Insert("ArrayListCache", LocalArrayList); 33:    ArrayListContents.DataSource = LocalArrayList; 34:    ArrayListContents.DataBind(); 35:    lblArrayListMessage.Text = "<b>ArrayList object put in the cache: </b>&nbsp;"; 36: 37:   }  else { 38: 39:    LocalArrayList = (ArrayList) Cache.Get("ArrayListCache"); 40:    ArrayListContents.DataSource = LocalArrayList; 41:    ArrayListContents.DataBind(); 42:    lblArrayListMessage.Text = "<b>ArrayList object from the cache: </b>&nbsp;"; 43: 44:   } 45:   //'***End*** 46: 47:  } 48: </script> 50: [VisualBasic.NET & C#.NET] 50: <html> 51: <body> 52:   <asp:Label runat="server" id="lblCacheTime" /> 53:  <p> 54:   <asp:Label runat="server" id="lblArrayListMessage" /> 55:   <asp:DropDownList id="ArrayListContents" runat="server" /> 56:  <p> 57: </body> 58: </html> 

In Listing 16.14, you are putting two objects into the cache, an ArrayList and a DateTime object. The first thing you want to do whenever you are getting and working with an object from the cache is check if they exist; if the item doesn't exist in the cache and you try to work with the returned object, you will receive a NullReferenceException . I check if these objects are in the cache on lines 9 (the DateTime object) and 24 (the ArrayList object). I use the Get method to retrieve the object and check whether it is null (C#.NET syntax) or nothing (VB.NET syntax). If either of the objects is found to be null, then you know that you have to re-create them and insert them back into the cache. If this is the first request to the page, then both the ArrayList and DateTime objects should be null. Because they both are null, the If statement is executed, and new DateTime and ArrayList objects are created ( DateTime , on line 11) and ( ArrayList , on lines 26 “30). After the item is created, you call the Cache.Insert method to insert each object into the cache (lines 12 and 32). This particular overload of Cache.Insert expects only two parameters:

  • string This string will be the Key for the cached item. The Key is used to access the object after it is in the cache.

  • Object The object you want to cache.

Note

This is the first overload for the Insert statement (the additional overloads are described in the following section). Using this overload of the Insert statement, cached items will remain in the cache for the lifetime of the application or until the runtime automatically takes it out due to lack of use or memory constraints.


You can see a screen shot of this page the first time it is requested in Figure 16.7. Notice that the Label control has the information from the If block ”"Object put into cache".

Figure 16.7. First request: Controls bound to dynamic data.
graphics/16fig07.gif

Now refresh the page. You will notice that the Label controls text now reads something like, "From the cache" (see Figure 16.8) On the page refresh, instead of dynamically creating each object, both objects were found in the cache. Hence, the else statement was executed, and the server controls were bound to the object obtained from the cache.

Figure 16.8. Second request: Controls bound to cached objects.
graphics/16fig08.gif

Now that you have a basic understanding of how to insert an item into the cache, let's go through the Insert method in detail.

The Insert Method

There are three other overloads to the Cache.Insert method available for your use. The following list contains all four:

  • Cache.Insert( String , Object )

  • Cache.Insert( String , Object , CacheDependency )

  • Cache.Insert( String , Object , CacheDependency , DateTime , TimeSpan )

  • Cache.Insert( String , Object , CacheDependency , DateTime , TimeSpan , CacheItemPriority , CacheItemPriorityDecay , CacheItemRemovedCallback )

The Cache.Insert method has the following parameters:

  • String ” The name of the key for the cache item.

  • Object ” The object you want to put into the cache.

  • CacheDependency ” A file or additional key of a cache item on which this cache item depends. If a change is made to a CacheDependency object (an XML Document), then this cache item becomes invalid and is taken out of the cache.

  • DateTime ” Sets the absolute expiration time for the cache item.

  • TimeSpan ” Sets the sliding expiration time for the cache item.

  • CacheItemPriority ” Sets the priority of the cache item relative to other cache items. The value of this parameter must be a member of the CacheItemPriority enumeration. A cache item with a lower priority will be taken out of the cache before one with a higher priority, in the event the server is under load.

  • CacheItemPriorityDecay ” Sets the rate at which an item declines in priority within the cache. The value of this parameter must be a member of the CacheItemPriorityDecay enumeration. With every thing else equal, a cache item that decays slowly will stay in the cache longer than one with a fast decay.

  • CacheItemRemovedCallback ” A delegate that will be called when the item is removed from the cache. One possible use could be to re-create an item when the item is taken out of the cache.

Using these parameters, you have incredible control over how an item is cached, and when the item is taken out of the cache. You now have all the possible overloads available to you using the Cache.Insert statement, so let's walk through inserting different types objects into the cache using a couple of them.

In Listing 16.15, I'll demonstrate how to insert an item into the cache that has a CacheDependency . This example uses the XML file Authors.xml , which is installed with the .NET SDK. Authors.xml can also be found in this book's source file.

Listing 16.15 Inserting an Item into the Cache That Has a CacheDependency
 [VisualBasic.NET] 01: <%@ Import Namespace="System.IO" %> 02: <%@ Import Namespace="System.Data" %> 03: 04: <script langauge="vb" runat="server"> 05: 06:  public sub Page_Load(sender as Object, e as EventArgs) 07: 08:   dim XmlDataSet as DataSet = CType(Cache.Get("XmlDataSetCache"),DataSet) 09: 10:   if XmlDataSet is nothing then 11: 12:    Response.Write("<b>Dynamically Created</b><p>") 13: 14:    dim ds as new DataSet() 15:    dim FStream as new FileStream(Server.MapPath("authors.xml"), _ 16:     FileMode.Open, FileAccess.Read) 17:    dim SReader as new StreamReader(FStream) 18:    ds.ReadXml(SReader) 19:    FStream.Close() 20: 21:    dg1.DataSource = ds 22:    dg1.DataBind() 23: 24:    Cache.Insert("XmlDataSetCache", ds, _ 25:     new CacheDependency(Server.MapPath("authors.xml")), _ 26:     DateTime.Now.AddSeconds(10), TimeSpan.Zero) 27: 28:   else 29: 30:    Response.Write("<b>From Cache</b><p>") 31: 32:    dg1.DataSource = XmlDataSet 33:    dg1.DataBind() 34: 35:  end if 36: 37: end sub 38: 39: </script> [C#.NET] 04: <script language="C#" runat="server"> 05: 06:  void Page_Load(Object sender, EventArgs e){ 07: 08:   DataSet XmlDataSet = (DataSet) Cache.Get("XmlDataSetCache"); 09: 10:   if (XmlDataSet == null) { 11: 12:    Response.Write("<b>Dynamically Created</b><p>"); 13: 14:    DataSet ds = new DataSet(); 15:    FileStream FStream = new FileStream(Server.MapPath("authors.xml"), 16:     FileMode.Open, FileAccess.Read); 17:    StreamReader SReader = new StreamReader(FStream); 18:    ds.ReadXml(SReader); 19:    FStream.Close(); 20: 21:    dg1.DataSource = ds; 22:    dg1.DataBind(); 23: 24:    Cache.Insert("XmlDataSetCache", ds, 25:     new CacheDependency(Server.MapPath("authors.xml")), 26:     DateTime.Now.AddSeconds(10), TimeSpan.Zero); 27: 28:   }  else { 29: 30:    Response.Write("<b>From Cache</b><p>"); 31: 32:    dg1.DataSource = XmlDataSet; 33:    dg1.DataBind(); 34: 35:  } 36: 37: } 38: 39: </script> [VisualBasic.NET & C#.NET] 41: <html> 42: <body> 43: 44:  <asp:DataGrid id="dg1" runat="server" font-size="10" /> 45: 46: </body> 47: </html> 

When the code from Listing 16.15 executes, the first thing you should do is check if the cache item exists already (lines 8 and 10). If the item is not found in the cache, then you create the DataSet object and bind the DataGrid by using the FileStream and StreamReader objects to retrieve the XML document and filling the DataSet by calling the DataSet.ReadXML method (lines 14 “22). Next, insert the file dependent DataSet into the cache (lines 24 “26). I used the third overload for the Insert method in this example. The first parameter is the name (Key) I want to use when referencing this cache item. The second parameter is the object I wanted to insert into the cache (the DataSet named ds ). The third parameter is a CacheDependency object. The CacheDependency object is created by passing in the path to the file on which you want this cache item to be dependent. The fourth parameter is the absolute expiration for the cache item and in this example it is set for 10 seconds. The fifth parameter is the cache items sliding expiration and in this example I used the Zero field that effectively set no sliding expiration. If the cache item does exist, then the DataGrid is bound directly to the XmlDataSet (lines 32 and 33). Figure 16.9 contains a screen shot of this page on the second request. Notice that "From Cache" is printed on the page.

Figure 16.9. The DataGrid is bound directly to the file-dependent DataSet retrieved from the cache.
graphics/16fig09.gif

We briefly went over the CacheDependency object in the proceeding paragraph. In Listing 16.15 we used a single file as the CacheDependency . There are two other overloads when constructing a CacheDependency object:

  • CacheDependency(string) ” Monitors a single file or directory for changes. The parameter is a file and/or directory path.

  • CacheDependency(string[]) ” Monitors an array of files or directories for changes. The parameter is a string array of file and/or directory paths.

  • CacheDependency(string[], string[]) ” The first parameter monitors an array of files or directories for changes. The second monitors an array of cache keys (other items in the cache). You can use one or the other or both at the same time. If you choose to just monitor by an array of cache keys specify null as the first parameter. The first parameter is a string array of file and/or directory paths. The second parameter is a string array of cache keys.

The Get Method

Getting an item from the cache is very easy. It is just a matter of calling the Cache.Get method and passing in the Key value of the object you want to retrieve. Because this method retrieves an object you can use it as though it were a local object by casting it. However, if you need to manipulate the data, it is a good idea to put it into a local variable.

Listing 16.16 illustrates a couple different methods you can use to work with data from the cache. This example inserts a new ArrayList into the cache and then retrieves it.

Listing 16.16 Using the Get Method to Retrieve Cached Items
 [VisualBasic.NET] 01: <script language="vb" runat="server"> 02: 03:  public sub Page_Load(sender as Object, e as EventArgs) 04: 05:  if CType(Cache.Get("ArrayListCache"),ArrayList) is nothing then 06: 07:   dim LocalArrayList as new ArrayList() 08:   dim i as integer 09:   for i = 0 to 10 10:    LocalArrayList.Add("Item - " & i) 11:   next i 12: 13:   Cache.Insert("ArrayListCache", LocalArrayList) 14:   ArrayListContents.DataSource = LocalArrayList 15:   ArrayListContents.DataBind() 16:   lblArrayListMessage.Text = "<b>ArrayList object put in the cache: </b>&nbsp;" 17: 18:  else 19: 20:   ArrayListContents.DataSource = CType(Cache.Get("ArrayListCache"), ArrayList) 21:   ArrayListContents.DataBind() 22:   lblArrayListMessage.Text = "<b>ArrayList object from the cache: </b>&nbsp;" 23: 24:  end if 25: 26:  end sub 27: 28: </script> [C#.NET] 01: <script language="c#" runat="server"> 02: 03:  void Page_Load(Object sender, EventArgs e){ 04: 05:  if (Cache.Get("ArrayListCache") == null){ 06: 07:   ArrayList LocalArrayList = new ArrayList(); 08:   int i; 09:   for(i = 0; i < 11; i++){ 10:    LocalArrayList.Add("Item - " + i); 11:   } 12: 13:   Cache.Insert("ArrayListCache", LocalArrayList); 14:   ArrayListContents.DataSource = LocalArrayList; 15:   ArrayListContents.DataBind(); 16:   lblArrayListMessage.Text = "<b>ArrayList object put in the cache: </b>&nbsp;"; 17: 18:  }  else { 19: 20:   ArrayListContents.DataSource = (ArrayList) Cache.Get("ArrayListCache"); 21:   ArrayListContents.DataBind(); 22:   lblArrayListMessage.Text = "<b>ArrayList object from the cache: </b>&nbsp;"; 23: 24:  } 25: 26: } 27: 28: </script> [VisualBasic.NET & C#.NET] 30: <html> 31: <body> 32: <asp:Label runat="server" id="lblArrayListMessage" /> 33: <asp:DropDownList id="ArrayListContents" runat="server" /> 34: <p> 35: </body> 36: </html> 

The Cache.Get method is first called on line 5 to check if the cache item exists. The Cache.Get method only requires one parameter and that is the cache Key or the name of the cache item you want to get. As in the previous example, check to see if the object is actually valid by using an if...then statement. If the object is not in the cache, re-create it and put it into the cache (lines 7 “16) and bind the DropDownList control. If it is in the cache, bind the DropDownList directly to the object (lines 20 “22).

The GetEnumerator Method

At some point, you might need to iterate through all the cache items. The Cache.Get Enumerator method can be used to return a IDictionaryEnumerator object you can use to do just that. The IDictionaryEnumerator object returned contains the Keys and their values. Listing 16.17 contains an example using the Cache.GetEnumerator method to print out all cache items to the page.

Listing 16.17 Retrieving a Dictionary Object of All Cached Items with the GetEnumerator Method
 [VisualBasic.NET] 01: <script language="vb" runat="server"> 02: public sub Page_Load(sender as Object, e as EventArgs) 03: 04:  dim myEnumerater As IDictionaryEnumerator 05:  myEnumerater = Cache.GetEnumerator() 06:  while(myEnumerater.MoveNext) 07:   Response.Write(myEnumerater.Key.ToString() & "<BR>") 08:  end while 09: 10: end sub 11: 12: </script> [C#.NET] 01:  <script language="c#" runat="server"> 02: void Page_Load(Object sender, EventArgs e){ 03: 04:  IdictionaryEnumerator myEnumerater; 05:  myEnumerater = Cache.GetEnumerator(); 06:  while(myEnumerater.MoveNext()) { 07:   Response.Write(myEnumerater.Key.ToString() + "<BR>"); 08:  } 09: 10: } 11: 12: </script> [VisualBasic.NET & C#.NET] 13: <html> 14: <body> 15: 16: </body> 17: </html> 

When the code in Listing 16.17 executes, you will receive a list of all items currently in the cache similar to Figure 16.10. Notice in that screen shot that the XmlDataSetCache cache item from the previous example is still in the cache.

Figure 16.10. The contents of this application's current cache. Notice that the XmlDataSetCache and ArrayListCache cache items are still present from the previous code examples.
graphics/16fig10.gif

Note

Because the contents of the cache might be changing constantly, some items returned by the Cache.GetEnumerator method might or might not still be in the cache.


The Remove Method

You might run into the need to remove items from the cache before they expire, either to refresh the data or because it is no longer needed and is just taking up memory. You can use the Cache.Remove method to removeq items from the cache. The Remove method takes only one parameter and that is the Key for the cached item and its return value is the object that was taken out of the cache. Listing 16.18 contains an example using the Cache.Remove method. In this example, you will remove the DataSet you inserted in Listing 16.15 ( XmlDataSetCache) . If it has been a while since you ran that example, you might want to extend the expiration time and run the page again to put the DataSet back into the cache.

Listing 16.18 Using the Remove Method to Remove a Cached Item
 [VisualBasic.NET] 01: <script language="vb" runat="server"> 02: 03:  public sub Page_Load(sender as Object, e as EventArgs) 04: 05:   Cache.Remove("XmlDataSetCache") 06: 07:  end sub 08: 09: </script> [C#.NET] 01: <script language="c#" runat="server"> 02: 03:  void Page_Load(Object sender, EventArgs e) { 04: 05:   Cache.Remove("XmlDataSetCache"); 06: 07: } 08: </script> [VisualBasic.NET & C#.NET] 11: <html> 12: <body> 13: </body> 14: </html> 

In Listing 16.18, the Cache.Remove method is called on line 5. The Remove method only expects one parameter, the Key for the cache item. If the cache item is found, it will be returned by the method and removed from the cache; if it doesn't exist, it will return a null reference. After running this page, go back and execute Listing 16.17 and you can verify that the item was indeed taken out of the cache.

only for RuBoard


Programming Data-Driven Web Applications with ASP. NET
Programming Data-Driven Web Applications with ASP.NET
ISBN: 0672321068
EAN: 2147483647
Year: 2000
Pages: 170

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net