ptg 1374 CHAPTER 29 Caching Application Pages and Data LISTING 29.26 ShowDynamicUserControl.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> void Page_Load() { // Load the control PartialCachingControl cacheMe = (PartialCachingControl)Page.LoadControl(“Movies.ascx”); // Change cache duration to 15 seconds cacheMe.CachePolicy.SetExpires(DateTime.Now.AddSeconds(15)); // Add control to page PlaceHolder1.Controls.Add(cacheMe); // Display control cache duration lblCacheDuration.Text = cacheMe.CachePolicy.Duration.ToString(); } </script> FIGURE 29.10 Programmatically caching a User Control. From the Library of Wow! eBook ptg 1375 Using DataSource Caching 29 <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show Dynamic User Control</title> </head> <body> <form id=”form1” runat=”server”> <div> Cache Duration: <asp:Label id=”lblCacheDuration” Runat=”server” /> <hr /> <asp:PlaceHolder id=”PlaceHolder1” Runat=”server” /> </div> </form> </body> </html> In Listing 29.26, the default cache duration is modified by modifying the PartialCachingControl’s CachePolicy property. This property returns an instance of the same ControlCachePolicy class described in the two previous sections of this chapter. You can refer to the User Control contained with an instance of the PartialCachingControl class by using the class’s CachedControl property. Normally, this property returns the value Nothing (null) because when the User Control is cached, it is never actually created. Using DataSource Caching Instead of caching at the page or User Control level, you can cache at the level of a DataSource control. Three of the four standard ASP.NET DataSource controls— SqlDataSource, ObjectDataSource, and XmlDataSource—include properties that enable you to cache the data that the DataSource control represents. (The LinqDataSource control does not support caching.) One advantage of using the DataSource controls when caching is that the DataSource controls can reload data automatically when the data is updated. For example, if you use a SqlDataSource control to both select and update a set of database records, the SqlDataSource control is smart enough to reload the cached data after an update. From the Library of Wow! eBook ptg 1376 CHAPTER 29 Caching Application Pages and Data The DataSource controls are also smart enough to share the same data across multiple pages. For example, when using the SqlDataSource control, a unique entry is created in the Cache object for each combination of the following SqlDataSource properties: SelectCommand, SelectParameters, and ConnectionString. If these properties are identical for two SqlDataSource controls located on two different pages, the two controls share the same cached data. NOTE DataSource caching does not work with LINQ to SQL queries. To learn about caching LINQ to SQL queries, see Chapter 20, “Data Access with LINQ to SQL.” In this section, you learn how to use the SqlDataSource, ObjectDataSource, and XmlDataSource controls to cache data. You learn how to set either an absolute or sliding expiration policy. Finally, you learn how to create a cache key dependency that you can use to expire the cache programmatically. Using an Absolute Cache Expiration Policy When you use an absolute cache expiration policy, the data that a DataSource represents is cached in memory for a particular duration of time. Using an absolute cache expiration policy is useful when you know that your data does not change that often. For example, if you know that the records contained in a database table are modified only once a day, there is no reason to keep grabbing the same records each and every time someone requests a web page. WARNING When caching with the SqlDataSource control, the SqlDataSource control’s DataSourceMode property must be set to the value DataSet (the default value) rather than DataReader. The page in Listing 29.27 displays a list of movies cached in memory. The page uses a SqlDataSource control to cache the data. LISTING 29.27 DataSourceAbsoluteCache.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>DataSource Absolute Cache</title> </head> From the Library of Wow! eBook ptg 1377 Using DataSource Caching 29 <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:SqlDataSource id=”srcMovies” EnableCaching=”True” CacheDuration=”3600” SelectCommand=”SELECT * FROM Movies” ConnectionString=”<%$ ConnectionStrings:Movies %>” Runat=”server” /> </div> </form> </body> </html> In Listing 29.27, two properties of the SqlDataSource control related to caching are set. First, the EnableCaching property is set to the value True. Next, the CacheDuration prop- erty is set to the value 3,600 seconds (1 hour). The movies are cached in memory for a maximum of 1 hour. If you don’t supply a value for the CacheDuration property, the default value is Infinite. You need to understand that there is no guarantee that the SqlDataSource control will cache data for the amount of time specified by its CacheDuration property. Behind the scenes, DataSource controls use the Cache object for caching. This object supports scav- enging. When memory resources become low, the Cache object automatically removes items from the cache. You can test whether the page in Listing 29.27 is working by opening the page and temporarily turning off your database server. You can turn off SQL Server Express by opening the SQL Configuration Manager located in the Microsoft SQL Server 2008 program group and stopping the SQL Server service (see Figure 29.11). If you refresh the page, the data displays even though the database server is unavailable. From the Library of Wow! eBook ptg 1378 CHAPTER 29 Caching Application Pages and Data Using a Sliding Cache Expiration Policy If you need to cache a lot of data, it makes more sense to use a sliding expiration policy rather than an absolute expiration policy. When you use a sliding expiration policy, data remains in the cache as long as the data continues to be requested within a certain interval. For example, imagine that you have been asked to rewrite the Amazon website with ASP.NET. The Amazon website displays information on billions of books. You couldn’t cache all this book information in memory. However, if you use a sliding expiration policy, you can cache the most frequently requested books automatically. The page in Listing 29.28 illustrates how you can enable a sliding cache expiration policy. The cache duration is set to 15 seconds. As long as no more than 15 seconds pass before you request the page, the movies are kept cached in memory. LISTING 29.28 DataSourceSlidingCache.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”> <script runat=”server”> protected void srcMovies_Selecting(object sender, ➥SqlDataSourceSelectingEventArgs e) { lblMessage.Text = “Selecting data from database”; } FIGURE 29.11 The SQL Configuration Manager. From the Library of Wow! eBook ptg 1379 Using DataSource Caching 29 </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>DataSource Sliding Cache</title> </head> <body> <form id=”form1” runat=”server”> <div> <p> <asp:Label id=”lblMessage” EnableViewState=”false” Runat=”server” /> </p> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:SqlDataSource id=”srcMovies” EnableCaching=”True” CacheExpirationPolicy=”Sliding” CacheDuration=”15” SelectCommand=”SELECT * FROM Movies” ConnectionString=”<%$ ConnectionStrings:Movies %>” OnSelecting=”srcMovies_Selecting” Runat=”server” /> </div> </form> </body> </html> The page in Listing 29.28 includes a srcMovies_Selecting() event handler. This handler is called only when the movies are retrieved from the database rather than from memory. In other words, you can use this event handler to detect when the movies are dropped from the cache (see Figure 29.12). From the Library of Wow! eBook ptg 1380 CHAPTER 29 Caching Application Pages and Data Caching with the ObjectDataSource Control The ObjectDataSource control supports the same caching properties as the SqlDataSource control. You can cache the data that an ObjectDataSource control represents by setting its EnableCaching, CacheDuration, and (optionally) CacheExpirationPolicy properties. NOTE Multiple ObjectDataSource controls can share the same cached data. To share the same cache, the ObjectDataSource controls must have identical TypeName, SelectMethod, and SelectParameters properties. For example, the page in Listing 29.29 uses an ObjectDataSource control to represent the Movies database table. The ObjectDataSource is bound to a component named Movie that includes a method named GetMovies() that returns all the records from the Movies data- base table. FIGURE 29.12 Using a sliding expiration policy with a DataSource control. From the Library of Wow! eBook ptg 1381 Using DataSource Caching 29 LISTING 29.29 ShowObjectDataSourceCaching.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <script runat=”server”> protected void srcMovies_Selecting(object sender, ➥ObjectDataSourceSelectingEventArgs e) { lblMessage.Text = “Selecting data from component”; } </script> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show ObjectDataSource Caching</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:Label id=”lblMessage” EnableViewState=”false” Runat=”server” /> <br /><br /> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:ObjectDataSource id=”srcMovies” EnableCaching=”true” CacheDuration=”15” TypeName=”Movie” SelectMethod=”GetMovies” OnSelecting=”srcMovies_Selecting” Runat=”server” /> </div> </form> </body> </html> From the Library of Wow! eBook ptg 1382 CHAPTER 29 Caching Application Pages and Data The ObjectDataSource control in Listing 29.29 includes an event handler for its Selecting event. The event handler displays a message in a Label control. Because the Selecting event is not raised when data is retrieved from the cache, you can use this method to determine when data is retrieved from the cache or the Movie component. The Movie component is contained in Listing 29.30. LISTING 29.30 Movie.cs using System; using System.Data; using System.Data.SqlClient; using System.Web.Configuration; public class Movie { public static DataTable GetMovies() { string conString = WebConfigurationManager.ConnectionStrings[“Movies”].ConnectionString; SqlDataAdapter dad = new SqlDataAdapter(“SELECT Title,Director FROM Movies”, conString); DataTable movies = new DataTable(); dad.Fill(movies); return movies; } } The GetMovies() method returns a DataTable. When using the ObjectDataSource control, you can cache certain types of data but not others. For example, you can cache data repre- sented with a DataSet, DataTable, DataView, or collection. However, you cannot cache data represented by a DataReader. If you attempt to bind to a method that returns a DataReader, an exception is thrown. Caching with the XmlDataSource Control Unlike the SqlDataSource and ObjectDataSource controls, the XmlDataSource control has caching enabled by default. The XmlDataSource automatically creates a file dependency on the XML file that it represents. If the XML file is modified, the XmlDataSource control automatically reloads the modified XML file. For example, the page in Listing 29.31 contains an XmlDataSource control that represents the Movies.xml file. If you modify the Movies.xml file, the contents of the files automati- cally reload. From the Library of Wow! eBook ptg 1383 Using DataSource Caching 29 LISTING 29.31 ShowXmlDataSourceCaching.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> <html xmlns=”http://www.w3.org/1999/xhtml” > <head id=”Head1” runat=”server”> <title>Show XmlDataSource Caching</title> </head> <body> <form id=”form1” runat=”server”> <div> <asp:GridView id=”grdMovies” DataSourceID=”srcMovies” Runat=”server” /> <asp:XmlDataSource id=”srcMovies” DataFile=”Movies.xml” Runat=”server” /> </div> </form> </body> </html> Creating a DataSource Control Key Dependency Imagine that your web application has multiple pages that display different sets of records from the Movies database table; however, you have one page that enables a user to enter a new movie. In that case, you need some method of signaling to all your DataSource controls that the Movies database table has changed. You can create a key dependency between the DataSource controls in your application and an item in the cache. That way, if you remove the item from the cache, all the DataSource controls reload their data. The page in Listing 29.32 contains a SqlDataSource control that displays the contents of the Movies database table. The SqlDataSource caches its data for an infinite duration. From the Library of Wow! eBook . ptg 13 74 CHAPTER 29 Caching Application Pages and Data LISTING 29.26 ShowDynamicUserControl.aspx <%@ Page Language=”C#” %> <!DOCTYPE html PUBLIC -/ /W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>. modifying the PartialCachingControl’s CachePolicy property. This property returns an instance of the same ControlCachePolicy class described in the two previous sections of this chapter. You can. eBook ptg 1378 CHAPTER 29 Caching Application Pages and Data Using a Sliding Cache Expiration Policy If you need to cache a lot of data, it makes more sense to use a sliding expiration policy