LISTING 29.26 ShowDynamicUserControl.aspx void Page_Load { // Load the control PartialCachingControl cacheMe = PartialCachingControlPage.LoadControl“Movies.ascx”; // Change cache dura
Trang 1LISTING 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
Trang 2<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
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
Trang 3The 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>
Trang 4<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
Trang 5Using 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
Trang 6</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)
Trang 7The 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
Trang 8LISTING 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>
Trang 9The 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
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
Trang 10LISTING 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>
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