Frequently Asked Interview Questions

Caching in ASP.NET

Caching is a way to store the frequently used data into the server memory which can be retrieved very quickly. And so provides both scalability and performance. For example if user is required to fetch the same data from database frequently then the resultant data can be stored into the server memory and later retrieved in very less time.
ASP.NET supports three types of caching for Web-based applications:
  • Page Level Caching (called Output Caching)
  • Page Fragment Caching (often called Partial-Page Output Caching)
  • Programmatic or Data Caching

Page Caching
Page level, or output caching, caches the HTML output of dynamic requests to ASP.NET Web pages. Caching in Asp.Net is implemented as an HttpModule that listens to all HttpRequests that come through the ASP.NET worker process. The OutputCacheModule listens to the application's ResolveRequestCache and UpdateRequestCache events, handles cache hits and misses, and returns the cached HTML, bypassing the page Handler if need be.
In order to cache a page's output, we need to specify an @OutputCache directive at the top of the page. The syntax is as shown below:
<%@ OutputCache Duration=5 VaryByParam="None" %>
The Duration parameter specifies how long, in seconds, the HTML output of the Web page should be held in the cache. When the duration expires, the cache becomes invalid and, with the next visit, the cached content is flushed, the ASP.NET Web page's HTML dynamically generated, and the cache repopulated with this HTML.
The VaryByParam parameter is used to indicate whether any GET (QueryString) or POST (via a form submit with method="POST") parameters should be used in varying what gets cached. In other words, multiple versions of a page can be cached if the output used to generate the page is different for different values passed in via either a GET or POST.
The VaryByParam is a useful setting that can be used to cache different "views" of a dynamic page whose content is generated by GET or POST values.
If there are two requests to the same page with varying querystring parameters, e.g.: .../PageCachingByParam.aspx?id=12 and .../PageCachingByParam.aspx?id=15] and separate page content is generated for each of them, the directive should be:
<%@ OutputCache Duration=5 VaryByParam="id" %>
The page content for the two requests will each be cached for the time specified by the Duration attribute. To specify multiple parameters, use semicolon to separate the parameter names. If we specify the VaryByParam attribute as *, the cached content is varied for all parameters passed through the querystring.
Fragment Caching
Instead of caching the complete page, some portion of the rendered html page is cached. E.g.: User Control used into the page is cached and so it doesn’t get loaded every time the page is rendered. 
<%@ OutputCache Duration=10 VaryByParam="None" %>
With the above directive, the user control content will be cached for the time specified by the Duration attribute [10 secs]. Regardless of the querystring parameters and browser type and/or version, the same cached output is served.
Data Caching:
We can store objects in memory and use them across various pages in our application. This feature is implemented using the Cache class. This cache has a lifetime equivalent to that of the application. Objects can be stored as name value pairs in the cache. 
A string value can be inserted into the cache as follows:
Cache["name"]=“XXXXXX";
Better approach is to use the Insert() method. It has four versions:
     1. Cache.Insert(key, value): Inserts an item into the cache under the specified key name, using the default priority and expiration.
     2. Cache.Insert(key, value, dependencies): Also includes a last parameter containing a CacheDependency object that links to other files or cached items and allows the cached item to be invalidated when these change.
     3. Cache.Insert(key, value, dependencies,absoluteExpiration, slidingExpiration): Also indicating sliding or absolute expiration policy(defined later on this section)
     4. Cache.Insert(key, value, dependencies,absoluteExpiration, slidingExpiration,onRemoveCallback): 
In addition, one can submit a delegate that points to a method you want invoked when the item is removed. 

Sliding Expiration and absolute Expiration: Both can't be used at the same time. If absolute expiration is used, set the slidingExpiration parameter to TimeSpan.Zero. To set a sliding expiration policy, set the absoluteExpiration parameter to DateTime.Max.
With sliding expiration, ASP.NET waits for a set period of inactivity to dispose of a neglected cache item. Here’s an example that stores an item with a sliding expiration policy of ten minutes, with no dependencies, So, the data will be removed only if it is not used within a ten-minute period.
Cache.Insert("MyItem",obj,null,DateTime.MaxValue, TimeSpan.FromMinutes(10))
With absolute expiration, we set a specific date and time when the cached item will be removed. Here’s an example that stores an item for exactly 60 minutes:
Cache.Insert("MyItem",obj,null,DateTime.Now.AddMinutes(60), TimeSpan.Zero)

Cache Dependency: Basically cache dependency falls under two categories:
1. File and Cache Item Dependency: Cache item can be dependent on a particular file. On modification of this file, cache will be invalidated.
         // Create a dependency for the ProductList.xml file.
         CacheDependency prodDependency = new  CacheDependency(Server.MapPath("ProductList.xml"));
         // Add a cache item that will be dependent on this file.
         Cache.Insert("ProductInfo", prodInfo, prodDependency);

        Cache can be dependent on other cached item as well. Create the array of cache keys and set the array as the dependency of other cache.
        Cache["Key1"] = "Cache Item 1";
       // Make Cache["Key2"] dependent on Cache["Key1"].
       string[] dependencyKey = new string[1];
       dependencyKey[0] = "Key1";
       CacheDependency dependency = new CacheDependency(null, dependencyKey);
       Cache.Insert("Key2", "Cache Item 2", dependency);
2. Dependencies on a database query: cache items can be depenedent on sql queries as well. In SQL Server 2000 and earlier version it was tedious task but the same is simplified in SQL Server 2005. It requires following few steps, as mentioned below:
1. Enable cache notification - Make sure your database has the ENABLE_BROKER flag set. Assuming we’re using the Northwind database:
Use Northwind
ALTER DATABASE Northwind SET ENABLE_BROKER
2. Create the cache dependency - As per below code line.
string query ="SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees";
SqlCommand cmd = new SqlCommand(query, strConnectionString);
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
// Fill the DataSet.
DataSet ds = new DataSet();
adapter.Fill(ds, "Employees");
// Create the dependency.
SqlCacheDependency empDependency = new SqlCacheDependency(cmd);
// Add a cache item that will be invalidated if one of its records changesor a new record is added.
Cache.Insert("Employees", ds, empDependency);
3. Call the static SqlDependency.Start() to initialize the listening service on the web server. This needs to be performed only once for each database connection. One place to call it is the Application_Start() method of the global.asax file.
4. Finally, call SqlDependency.Stop() to detach the listener. Typically, this is called under Application_End() method.

Most Visited Pages

Home | Site Index | Contact Us