Thiru Thangarathinam
In ASP.NET 2.0, caching has been improved in a couple of notable ways. Probably the most interesting feature is the introduction of database-triggered cache invalidation. In ASP.NET 1.x, you can invalidate a cached item based on some pre-defined conditions such as change in an XML file or change in another cache item. Using this feature, you can remove or invalidate an item from the cache when the data or another cached item changes. However, the ASP.NET 1.x Cache API does not allow you to invalidate an item in the cache when data in a SQL Server database changes. This is a very common capability most applications will require. ASP.NET 2.0 addresses this by providing the database triggered cache invalidation capability to ensure that the items in the cache are kept up-to-date with the changes in the database. You can accomplish this using any one of the following methods.
Declarative Output caching - This is similar to declarative output caching in ASP.NET 1.x, wherein you configure caching by specifying the OutputCache directive and their related attributes.
Programmatic Output caching - In this method, you will use the SqlCacheDependency object programmatically to specify the items to be cached and set their attributes.
Cache API - In this option, you will use the static methods of the Cache class such as Insert, Remove, Add and so on to add or remove items from the ASP.NET cache, while still using the SqlCacheDependency object to trigger the cache invalidation.
Another important caching feature in ASP.NET 2.0 is the ability to create custom cache dependencies, which is not possible with ASP.NET 1.x Cache API. To accomplish this, you need to inherit from the CacheDependency class. Since the CacheDependency is a sealed class in ASP.NET 1.x, you can't inherit and extend it. However, in ASP.NET 2.0, this is no longer the case. You can inherit from CacheDependency class and create your own custom cache dependencies. This opens up a world of opportunities where you can roll your own custom cache dependencies required for a particular class of applications. For example, you can create a StockPriceCacheDependency class that automatically invalidates the cached data when the stock price changes.
SQL Server-Based Cache Invalidation Mechanism
The SQL Server based cache invalidation mechanism works with SQL Server 7.0 and above. However, with SQL Server 7.0 and 2000, only Table level cache invalidation mechanism is supported. This means that the cached items will be automatically invalidated any time the data in the table changes. The next release of SQL Server (code-named Yukon) will also feature row-level cache invalidation mechanism, providing a finer level of accuracy over the cached data.
In SQL Server 7 and SQL Server 2000, table level cache invalidation is supported using a polling system. Through this system, the ASP.NET process will poll the database (pull model) every so many seconds to check and see which tables have changed since it last checked. Even though the pull model works for most cases, it is not an efficient approach. However, this will be enhanced in Yukon to have Yukon actually notify (Push model) ASP.NET whenever a particular row of data has been modified. Yukon accomplishes this by using a feature called Notification Delivery Services (that uses ports 80), which directly interacts with HTTP.SYS of IIS 6.0 to notify the Web server of updates to the specific rows. For the purposes of this article, you will consider SQL Server 7 and 2000 and understand how to configure caching for those versions.
Before you can establish cache dependency with SQL Server 7 or SQL Server 2000, you need to perform the following steps.
You must have
You also need to perform one-time setup of the tables or databases you want to monitor using either the aspnet_regsqlcache utility or the EnableTableForNotifications method.
After you have completed the above steps, ASP.NET can start invalidating the data in the cache when the SQL Server data changes, which is accomplished by a polling mechanism approach. Note that with Yukon, the above steps are not required. Before looking at the three different ways to enable SQL Server based caching, you should understand the steps that are required for the caching to work.
First and foremost, you need to ensure your web.config file contains the appropriate cache related settings. The web.config file should contain a cache element as shown below.
???
???????
???
???
?????? ??
?????? ?? ???
?????? ???????????
???????????????????? ???? ? ?
????????????? ?????
?????????????
? ???? ????
???
?????? ---------
?????? ---------
In the above configuration entries, you specify the name of the database in which you want to enable the cache notification mechanism using the
Next step is to enable the specific tables in the Northwind database for notification. You can perform this using any one of the following two ways:
Using the aspnet_regsqlcache utiltity. You will see an example of this shortly.
Using the EnableTableForNotifications method of the SqlCacheDependencyAdmin class.
Once you configure the table to send notifications, any time data in the table changes, it notifies ASP.NET to invalidate the specific item in the cache. For the purposes of this article, consider the aspnet_regsqlcache utility to configure the tables. Basically this utility creates an extra table named AspNet_SqlCacheTablesForChangeNotification that is used to keep track of the changes to all the monitored tables in the database. It also creates a number of triggers and stored procedures to enable this capability. To run the aspnet_regsqlcache utility, open up the Visual Studio .NET command prompt and enter the command shown in the following screenshot.
In the above command:
S - Name of the Server
U - User ID to use to connect to the SQL Server
P - Password to use to connect to the SQL Server
d - Specifies the name of the database
t - Table to configure
et - enables the tables for SQL Server database triggered invalidation
As mentioned before, you need to follow the above steps only when you use SQL Server 7 or SQL Server 2000. If you are using the next version of SQL Server (code-named Yukon), the above configurations are not necessary. Moreover the cache invalidating mechanism works through a highly efficient notification model, wherein the Notification Delivery Service component of SQL Server directly notifies IIS using TCP Port 80 when the data in a SQL Server changes.
Now that you understood the steps required for enabling this, take a look at the different ways of caching ASP.NET pages so that it takes advantage of SQL Server trigger based cache invalidation mechanism.
Declaratively enabling caching using OutputCache directive
In this section, you will see how to enable output caching declaratively using the OutputCache directive. Here's the complete code of the ASP.NET page.
???????
?????? DataSet categories = new DataSet();
?????? adapter.Fill(categories);
?????? SqlCacheDependency dependency = new
SqlCacheDependency("Northwind", "Categories");
?????? Response.AddCacheDependency(dependency);
?????? Response.Cache.SetValidUntilExpires(true);
?????? Response.Cache.SetExpires(DateTime.Now.AddMinutes(60));
?? ????Response.Cache.SetCacheability(HttpCacheability.Public);
?????? gridCategories.DataSource = categories;
?????? gridCategories.DataBind();????????????????
?????? Response.Write("Page created on : "? + DateTime.Now.ToString());??????????????
??? }???
???
???
???????
???????
?? ?
The above code is similar to the previous example except that the caching is performed programmatically. In the Page_Load event, you create an instance of the SqlConnection object and pass in the connection string as an argument. To retrieve the connection string from the web.config file, you use one of the new classes supplied by ASP.NET 2.0, named ConnectionStrings, that provides helper properties to retrieve the connection strings specified in the connectionStrings section of the web.config file. You then create an instance of the SqlDataAdapter object passing in the SQL to be executed and the SqlConnection object as its arguments. After that you create an instance of the DataSet object and then fill the dataset object by invoking the Fill method of the SqlDataAdapter object. Then you create an instance of the class named SqlCacheDependency passing in the database and the table to be monitored as its arguments. You also add the SqlCacheDependency object to the Response object using the AddCacheDependency method. After that, you set various attributes of the Cache object. Finally, you bind the output of the returned data to the GridView control. Navigating to the above page results in an output that is similar to our previous example. To test this page, change the data in the categories table and see the change in the date time displayed in the page.
Cache API Example
So far, you have seen how to use the output caching declaratively and programmatically to enable caching on ASP.NET pages. In this section, you will see how to use the Cache API to accomplish the same functionality. As in ASP.NET 1.x, the Cache API is very powerful in that it not only provides complete control over how items are cached but also enables the execution of some code when an item is removed or invalidated from the cache. The following code shows an example of using Cache API to control caching for an ASP.NET page.
?
??? void Page_Load(object sender, System.EventArgs e)
??? {???????
??????? DataSet categories;???????
??????? categories = (DataSet)Cache["Categories"];
??????? if (categories == null)
??????? {
??????????? SqlConnection conn = new
?SqlConnection(
ConfigurationSettings.ConnectionStrings["Northwind"]);
??????????? SqlDataAdapter adapter = new
SqlDataAdapter("Select * from Categories", conn);
??????????? categories = new DataSet();
??????????? adapter.Fill(categories);
??????????? SqlCacheDependency dependency = new
????????????? SqlCacheDependency("Northwind", "Categories");
??????????? Cache.Insert("Categories", categories, dependency);
??????????? Response.Write("Categories retrieved from the database");???????
??????? }
??????? else
??????????? Response.Write("Categories retrieved from the Cache");???????
???????
??????? gridCategories.DataSource = categories;
??????? gridCategories.DataBind();????????????????????????
??? }
???
???
???
????????
???????
???
The above code is very similar to the previous example, except in this case, the Insert method of the Cache class is used to add items to the cache. In the above code, you start by creating an instance of the SqlConnection object passing in the connection string that is retrieved from the web.config file. Then you create an instance of the SqlDataAdapter object and pass in the SQL statement to be executed and the previously created SqlConnection object as its arguments. Then you execute the SQL query using the Fill method of the SqlDataAdapter object. After that you create an instance of the SqlCacheDependency object and supply the database name (that corresponds to the database name specified in the web.config file) and the table name as its arguments. Then you insert the categories dataset to the cache using the Insert method of the Cache object. At the time of inserting, you should also specify the SqlCacheDependency object so that the categories dataset can be invalidated when the data in the categories table changes. Finally, you sould bind the categories dataset to the GridView control.
When you navigate to the above page using the browser, you get the following output, which clearly shows that for the first time the categories information is retrieved from the database.
If you refresh the browser, you will see the following output, in which the categories information is retrieved from the cache.
To test if the SQL Server based cache invalidation mechanism works, modify the data in the Categories table and then if you navigate to the page using the browser, you will get a message stating that the categories is retrieved from the database.
Creating Custom Cache Dependencies
So far, you have used the built-in SqlCacheDependency class for invalidating the cached item when the data in the SQL Server database changes. Even though this approach is very useful, there are times you might want to create your own custom cache dependency. For example, when the stock price changes, you might want to invalidate an item in the cache. ASP.NET 2.0 Cache API enables these types of scenarios by providing the ability to create custom cache dependency classes that are inherited from the CacheDependency class.
Conclusion
The Cache API introduced with ASP.NET 1.0 was a powerful feature that could be immensely useful in increasing the performance of a Web application. The Cache API in ASP.NET 2.0 builds on the foundation provided by the ASP.NET 1.0 and makes it extremely easy and seamless to build high performance ASP.NET applications. Being able to invalidate a cached item when the data in the database changes is a capability that can go a long way in revolutionizing the way ASP.NET applications are built and deployed. Furthermore, the ability to create custom cache dependencies (when one of the built-in cache dependency classes does not suit your needs) enables a whole lot of impressive caching scenarios for the developers to take advantage of.
About the Author
Thiru has many years of experience in architecting, designing, developing and implementing applications using Object Oriented Application development methodologies. He also possesses a thorough understanding of software life cycle (design, development and testing).
He is an expert with ASP.NET, .NET Framework, Visual C#.NET, Visual Basic.NET, ADO.NET, XML Web Services and .NET Remoting and holds MCAD for .NET, MCSD and MCP certifications.
Thiru has authored numerous books and articles. He can be reached at thiruthangarathinam@yahoo.com.
Back to article
Copyright 2005 Jupitermedia Corp. All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.
http://www.internet.com
2 comments:
not too bad
try more..
Post a Comment