17 August, 2011

Types of Caching in Asp.net

Asp.net and the .NET Framework enable you to take advantage of caching without requiring
you to write a lot of code to deal with the complexities of caching, such as cache expiration,
updates, and memory management. There are two different types of caching in ASP.NET:

■ Application caching

This represents a collection that can store any object in memory
and automatically remove the object based on memory limitations, time limits, or
other dependencies.

■ Page output caching

This is ASP.NET’s ability to store a rendered page, portion of a
page, or version of a page in memory to reduce the time required to render the page

Application Caching in Asp.net

Application Caching (also called application data caching) is the process of storing data (not
pages) in a cache object. The cache object is available as a property of the Page object. It
represents a collection class of type System.Web.Caching.Cache. The Page.Cache property
actually uses an application-wide cache (not just a page-specific cache). This means that
a single Cache object exists for your entire application; items in the Cache can be shared
between user sessions and requests.

Using the Cache Object

You work with the Cache object as you would with Session or similar objects. You can assign
items directly to the cache by giving them a name (key) and assigning them an object (value).
You retrieve objects from the cache by checking for the key.
Always verify that an item is not null. If a value is null, that value either hasn’t been cached
or it has expired from the cache. If an item is null, you should retrieve it from the original source
and, in most cases, place it into the cache.

The following code sample demonstrates how to cache and retrieve a String object with
the Cache collection.

Sample of Visual Basic Code
Cache("Greeting") = "Hello, cache!"
If Cache("Greeting") IsNot Nothing Then
Label1.Text = DirectCast(Cache("Greeting"), String)
Else
Label1.Text = "Hello, world!"
End If

Sample of C# Code
Cache["Greeting"] = "Hello, cache!";
if (Cache["Greeting"] != null)
Label1.Text = (string)Cache["Greeting"];
else
Label1.Text = "Hello, world!";

You wouldn’t normally cache a static string in your application; you’d more likely cache a file,
a database query result, or other data that is shared and expensive to obtain. You can cache any
object type, including your own custom types as long as they are serializable. However, just
as you would from any generic collection, you must cast the object back to the correct type
when you access it from the cache.



Inserting Items into the Cache

The previous example demonstrates that you can use the Cache object as you would Session or
Application. You can access much more sophisticated functionality, however, by using the Insert
method to add an item to the cache and control how that item gets removed from the cache.
This functionality includes automatic removal based on a specific period of time, removal when
a file changes, or removal when another cache object expires.

Insert has a number of overloads based on the many parameters you can set when adding
an item to the cache.
 The following list outlines the parameters of the Cache.Insert method:

■ key  This is the name (as a String) that you’ll use to access the cached object in the
Cache collection. The key must be unique in the cache.
■ value This is the data (as an Object) that you want to cache.
■ dependencies  A CacheDependency object identifies a file or a key to another item in
the cache. When the file or related cached item is changed, this will trigger this cached
object to be removed from the cache.If you cache a file, you should configure a dependency for the file so that it is removed from the cache after being modified. This helps ensure that your cache never becomes
stale. You might also call the parameter onRemoveCallback to reload the cached item.
■ absoluteExpiration  This is the time (as a DateTime object) at which the object
should be removed from the cache. This is absolute and therefore does not take
into consideration whether the item has been recently accessed by a user. If you
do not wish to use absolute expiration, you can set this property to System.Web
.Caching.Cache.NoAbsoluteExpiration.
■ slidingExpiration  This is the time (as a TimeSpan object) after which the object
should be removed from the cache if it has not been accessed by a user. Set this to
System.Web.Caching.Cache.NoSlidingExpiration if you don’t want to use it.
■ priority  This is a CacheItemPriority enumeration value that you can use to determine
which objects are removed first when memory starts to run low (this process is called
scavenging). Lower priority objects are removed sooner. The values for priority, from
lowest (most likely to be removed) to highest (least likely to be removed) include the
following:
  1. ■ Low
  2. ■ BelowNormal
  3. ■ Normal (Default is equivalent to Normal)
  4. ■ AboveNormal
  5. ■ High
  6. ■ NotRemovable
■ onRemoveCallback This is an event handler that is called when the object is removed
from the cache. This can be null if you don’t want to specify a callback method.
(FOR MORE CLEAR VISION VISIT :-http://msdn.microsoft.com/en-us/library/05kd8d77.aspx)

Defining a Cache Dependency


A cache dependency links a cached item to something else such as a file or another item in
the cache. ASP.NET monitors the dependency and invalidates the cache if the dependent
item changes. The following code sample demonstrates how to make a cache dependency
based on a file. If the file the cache is dependent upon changes, the object is removed
from the cache.

Sample of Visual Basic Code
Cache.Insert("FileCache", File.ReadAllText("SourceFile.txt"), _
New System.Web.Caching.CacheDependency(Server.MapPath("SourceFile.txt")))

Sample of C# Code
Cache.Insert("FileCache", File.ReadAllText("SourceFile.txt"),
new System.Web.Caching.CacheDependency(Server.MapPath("SourceFile.txt")));

You can also create multiple dependencies for a single cached item. The following
example demonstrates how to use an AggregateCacheDependency object to add an item
to the cache that is dependent on both an item named CacheItem1 and a file named
SourceFile.xml.

Sample of Visual Basic Code
Dim dep1 As CacheDependency = New CacheDependency(Server.MapPath("SourceFile.txt"))
Dim keyDependencies2 As String() = {"CacheItem1"}
Dim dep2 As CacheDependency = New System.Web.Caching.CacheDependency(Nothing, _
keyDependencies2)
Dim aggDep As AggregateCacheDependency = New System.Web.Caching.
AggregateCacheDependency()
aggDep.Add(dep1)
aggDep.Add(dep2)
Cache.Insert("FileCache", File.ReadAllText("SourceFile.txt"), aggDep)

Sample of C# Code
System.Web.Caching.CacheDependency dep1 =
new System.Web.Caching.CacheDependency(Server.MapPath("SourceFile.txt"));
string[] keyDependencies2 = { "CacheItem1" };
System.Web.Caching.CacheDependency dep2 =
new System.Web.Caching.CacheDependency(null, keyDependencies2);
System.Web.Caching.AggregateCacheDependency aggDep =
new System.Web.Caching.AggregateCacheDependency();
aggDep.Add(dep1);
aggDep.Add(dep2);
Cache.Insert("FileCache", File.ReadAllText("SourceFile.txt"), aggDep);


Setting an Absolute Cache Expiration


To cache an object for a set amount of time, pass the absoluteExpiration parameter to the
Cache.Insert method. This parameter sets a time in the future at which your data should
expire. The DateTime.Now object has a variety of methods for adding a specific number
of minutes to the current time. The following example demonstrates this.

Sample of Visual Basic Code
Cache.Insert("FileCache", "CacheContents", Nothing, DateTime.Now.AddMinutes(10), _
Cache.NoSlidingExpiration)
Sample of C# Code
Cache.Insert("FileCache", "CacheContents", null, DateTime.Now.AddMinutes(10),
Cache.NoSlidingExpiration);

Setting a Sliding Cache Expiration


If you want your most frequently used cached objects to stay in your cache longer, you can
specify a sliding expiration. A sliding expiration indicates the amount of time that must elapse
between subsequent requests before an item is removed from the cache. Each time a new
request comes in for an item, the sliding scale restarts.
You set a sliding expiration by passing a TimeSpan to the slidingExpiration parameter
of the Insert method. The TimeSpan is the time after the last read request that the cached
object will be retained. This example shows you how to keep an object in cache for 10
minutes after the last request.


Sample of Visual Basic Code
Cache.Insert("CacheItem7", "Cached Item 7", _
Nothing, System.Web.Caching.Cache.NoAbsoluteExpiration, New TimeSpan(0, 10, 0))
Sample of C# Code
Cache.Insert("CacheItem7", "Cached Item 7",
null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0));

Especially with a sliding cache expiration, it is possible that heavy usage will result in an
item never being removed from the cache, preventing updates to the original object from
being accessed. By defining an absolute expiration in addition to a sliding expiration, you
can be sure an object is eventually removed. When possible, add a cache dependency to
your absolute and sliding cache expirations to immediately remove the cached object
when the original is updated.



ASP.NET Caching Dependencies in Asp.net


Caching can depend on several items which include user request, file, database tables, table rows, duration, user controls, query strings, browsers and also other cached items. Let's start with the Caching dependency on other cached items.


Caching Dependency on Cached Items

It is interesting to note that your cached item can depend on other cached items. This means that if the item A is removed from the cache you can also remove item B from the cache. Let's start by creating and inserting the item A and item B in the Cache object.



protected void Button_Click(object sender, EventArgs e)
{
    // create item A and item B

    string itemA = "ItemA";
    string itemB = "ItemB";
    Cache.Insert("ItemA", itemA, null, DateTime.Now.AddMinutes(10), 
    TimeSpan.Zero,
    CacheItemPriority.Default, MyItemRemovedCallBack);
    Cache.Insert("ItemB", itemB, null, DateTime.Now.AddMinutes(10), 
    TimeSpan.Zero,
    CacheItemPriority.Default, MyItemRemovedCallBack);
}

In the code above I am creating two items "itemA" and "itemB". After creating the items I simply put the items in the Cache object using the Insert method. The last parameter is the callback method "MyItemRemovedCallBack" which will be fired when either of the two items is removed from the Cache.

It is not a good idea to insert the items into the Cache inside the callback method because you might not need the item right away and hence you will be wasting valuable resources to create them.

Let's take a look at the MyItemRemovedCallBack implementation.
private void MyItemRemovedCallBack(string key, object value,
                   CacheItemRemovedReason reason)
{
    // remove the item from the cache

    if (key == "ItemA" ) Cache.Remove("ItemB");
    else if (key.Equals == "ItemB") Cache.Remove("ItemB");
}

The MyItemRemovedCallBack method takes three parameters.

key: This is the key which is used to identify the items in the Cache.
value: The value assigned to the item which is inserted in the Cache.

reason: The variable "reason" is of type CacheItemRemovedReason enumeration and it identifies the reason the item was removed from the Cache.

The code given below removes an item from the Cache and as soon as the item is removed the "MyItemRemovedCallBack" method is fired and removed the other item from the Cache.
protected void Btn_RemoveCacheItem(object sender, EventArgs e)
{
    Cache.Remove("ItemA");
}


Cache Dependency on SQL

My main goal of this post is cache base on sql.

In simple words,caching can also depend on the database table means that your chaching value will remains in memory untill table in the database updates.so, when you will fire INSERT,UPDATE or DELETE quary on table,it will chage the table data so will remove chache automatically from memory and reload it again from the Connection string you have defined.

lets see in detail :

------------------------------------------------------------------------------------------------

First of all, you have tp enable the SQ Cache dependency on database to perform this opration. you can not cache particulat database or table without doing this settings. 

You can enable the SQL Cache dependency by using the aspnet_regsql.exe command line tool. to enable it perform following steps :

open command line prompt by going to start->run->cmd.

Then navigate to framework path of your system.

for eg:  cd C:\Windows\Microsoft.NET\Framework\v2.0.50727

Then, run this command--> aspnet_regsql.exe -S localhost -ed  -E -d DatabaseName
this means , you are trying to enable(-e) SQl DEPENDENCY option for particular database (-d) on localhost.
for eg:  my database name is "db1" then-->  aspnet_regsql.exe -S localhost -ed  -E -d db1

Then, enable SQl DEPENDENCY for table in the database like this.-->
aspnet_regsql.exe -S localhost -et  -E -d DatabaseName -t TableName


-------------------------------------------------------------------------------------------------------------------------------------


The next step is to create the connectionString in the connectionStrings section andsqlCacheDependency in the web.config file. Take a look at the code below:

Note : here i have one database having name "School" with table "Users".

    



    
        
            
                
            
        
    

As, you have noticed that the sqlCacheDependency have a pollTime attribute which is set to "1000" milliseconds. This means that the ASP.NET will check the database table for any changes every 10 seconds. The database section of the contains the connectionString which is used to connect to the database.

The final step is to use the caching in your code. You can do this in various ways. Take a look at the following code which uses caching programmatically.

private void BindData()
{
    // if null then fetch from the database

    if (Cache["Users"] == null)
    {
        // Create the cache dependency

        SqlCacheDependency dep = new SqlCacheDependency("School", "Users");
        string connectionString = ConfigurationManager.ConnectionStrings[
                                        "ConnectionString"].ConnectionString;
        SqlConnection myConnection = new SqlConnection(connectionString);
        SqlDataAdapter ad = new SqlDataAdapter("SELECT FirstName, LastName " +
                                               "FROM Users", myConnection);
        DataSet ds = new DataSet();
        ad.Fill(ds);

        // put in the cache object

        Cache.Insert("Users", ds, dep);
    }

    gvUsers.DataSource = Cache["Users"] as DataSet;
    gvUsers.DataBind();
}

The line SqlCacheDependency dep = new SqlCacheDependency("School", "Users"); is used to create the caching on the School database and Users table. In the beginning of the BindData method I check that if the item is already in the Cache. If it is then I simply return the item using caller by casting it from the Cache object. If the item is not in the Cache then the data is fetched from the database and inserted into the Cache object. The Cache will be discarded anytime you make a change in the database table "Users". This means that if you INSERT, DELETE, UPDATE any data in any row in the Users table then the Cache will be considered obsolete and a copy of the fresh data will be fetched from the database.

Caching in SQL Server 2005 have a different architecture then in SQL Server 2000. You don't have to write any lines in web.config to enable Caching in SQL Server 2005. Also, in SQL Server 2005 the Cache is only expired when the row is changed in the database table.

Creating a Cache Page Output Dependency in Asp.net

To create a cache page output dependency, call one of the following Response methods:
1) Response.AddCacheDependency
This makes the validity of a cached response dependent on a CacheDependency object.

In ASP.NET 2.0, developers are free to develop their own custom cache dependencies. The CacheDependency class allows for the creation of a custom cache dependency based on files, directories, or cache keys.
For example, the code below creates a new custom cache dependency based on a file called stuff.xml located in the root of the Web application:
System.Web.Caching.CacheDependency dep = new
System.Web.Caching.CacheDependency(Server.MapPath("stuff.xml"));
Response.AddCacheDependency(dep);
Cache.Insert("key", "value");

In this scenario, when the stuff.xml file changes, the cached item is invalidated.
It is also possible to create a custom cache dependency using cache keys. Using this method, the removal of the cache key will invalidate the cached data. The following example illustrates this:
// insert a value into cache that will serve
// as the cache key
Cache["CacheKey"] = "something";

// create an array of cache keys
string[] keys = new String[1];
keys[0] = "CacheKey";

CacheDependency dep = new CacheDependency(null, keys);

// insert an item into cache with a dependency on
// the above CacheDependency
Cache.Insert("Key", "Value", dep);
  To invalidate the item that was inserted above, simply remove the item that was inserted into cache to act as the cache key.
// Remove the cache item that serves as the cache key
Cache.Remove("CacheKey");
 

2) Response.AddCacheItemDependency and Response.AddCacheItemDependencies
These make the validity of a cached response dependent on one or more other
items in the cache.


When you add pages to the output cache, the page will be removed when the amount of time you specify in the expiration policy has passed. There are times when you want a page, or versions of a page, to be removed from the output cache before it has expired. For example, if your page displays volatile data, such as a stock price or a temperature, the page will display incorrect information if the data is updated before the page expires.
To address this issue, ASP.NET provides the HttpResponse.AddCacheItemDependency and HttpResponse.AddCacheItemDependencies methods, which allow you to cache page output that is dependent upon an item in the Cache object (associated with the application that the page belongs to).

The AddCacheItemDependency method allows you to create a relationship between the page and a single item in the Cache, while the AddCacheItemDependencies method allows you to create relationship between the page and an array of Cache items. When any of the items upon which the page is dependent change or are removed from the application Cache, the page output is invalidated and removed from the output cache. 

Note   You cannot use these methods from a Web Forms user control.


To make cached page output dependent upon a Cache item
  1. Specify the settings for caching page output either declaratively or programmatically.
  2. In the code-declaration block or the code-behind file for the page, add an item to your Web application's Cache object using the Cache.Item property, the Cache.Addmethod, or the Cache.Insert method.
  3. In the code-declaration block or the code-behind file for the page, use Response object syntax to call the AddCacheItemDependency or AddCacheItemDependenciesmethod, specifying the cached item or items upon which the page is dependent.
The following example assumes that an application contains a temperature component. The component uses the Cache.Insert method to place a temperature into the application Cache. 
Cache.Insert("Temperature.CurrentTemperature", currentTemperature);

The following page code, found in a code-declaration block or code-behind file, gets the current temperature stored in the Cache, converts it to a string, and then displays it. It then makes its output cache version dependent upon the Temperature.CurrentTemperature key. From this point forward, when the temperature component updates the temperature, the page version is flushed from the output cache. The page will be placed in the output cache again when it is subsequently requested.

int temperature = (int) Cache.Get("Temperature.CurrentTemperature");
LabelTemperature.Text = temperature.ToString();
Response.AddCacheItemDependency("Temperature.CurrentTemperature");

[Visual Basic]
Dim temperature as Integer
temperature = Cache.Get("Temperature.CurrentTemperature")
LabelTemperature.Text = temperature.ToString()
Response.AddCacheItemDependency("Temperature.CurrentTemperature")

3) Response.AddFileDependency and Response.AddFileDependencies
These make the validity of a cached response dependent on one or more files.


At times you might want to remove a page from the output cache when a file changes. For example, you might have a page that gets its contents from a process-intensive report that produces an XML file as output. The page needs to be reprocessed only if the XML file changes. To limit reprocessing to just those times when it is necessary, you can use the make the page's cache policy dependent on a single file. If required, you can make the cached page dependent on more than one file.

To make cached page output dependent upon a file

  1. Specify the settings for caching page output either declaratively or programmatically.
  2. In the page code, call the AddFileDependency method. As the method's filename parameter, pass the path of the file on which you are creating a dependency.
The following code example sets a file dependency on the TextFile1.txt file. When the file changes, the page output will be removed from the cache.

protected void Page_Load(object sender, EventArgs e)
{
    string fileDependencyPath = Server.MapPath("TextFile1.txt");
    Response.AddFileDependency(fileDependencyPath);

    // Set additional properties to enable caching.
    Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
    Response.Cache.SetCacheability(HttpCacheability.Public);
    Response.Cache.SetValidUntilExpires(true);
}

To make cached page output dependent on a group of files

  1. Specify the settings for caching page output either declaratively or programmatically.
  2. In the page code, create a String array or an ArrayList that contains the paths of the files to make the page dependent on.
  3. Call the AddFileDependencies method and as the filenames parameter, pass the array.
The following code example creates a string array of the file paths for the TextFile1.txt and XMLFile1.xml files and makes the page output dependent on the two files. If either one of the files is modified, the page output will be removed from the cache.

protected void Page_Load(object sender, EventArgs e)
{
    string[] fileDependencies;
    string fileDependency1 = Server.MapPath("TextFile1.txt");
    string fileDependency2 = Server.MapPath("XMLFile1.xml");
    fileDependencies = new String[] { fileDependency1, 
        fileDependency2 };
    Response.AddFileDependencies(fileDependencies);
}

Programmatically Invalidating Cached Pages in Asp.net

Often you want to cache pages, but specific events might require you to stop using the
cached page. For example, a page that displays results from a database query should only
be cached until the results of the database query change. Similarly, a page that processes a
file should be cached until the file is changed. Fortunately, ASP.NET gives you several ways
to invalidate cached pages.

Determining Whether to Return a Cached Page Prior to Rendering

To directly control whether a cached version of a page is used or whether the page is
dynamically regenerated, respond to the MycacheValidate (Manualy created event) event and set a valid value
for the HttpValidationStatus attribute. Then, from the Page.Load event handler, call the
AddValidationCallback method and pass an HttpCacheValidateHandler object with your method.

The following example demonstrates how to create a method to handle the ValidatePage
event.
.aspx file
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ OutputCache Duration="30" VaryByParam="mode" %>


    Validating Cache


    
Cache Time: Real Time:
.cs file
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

public partial class _Default : System.Web.UI.Page 
{
    // load event will run every 30 seconds , because it will be cached for 30 seconds.
    protected void Page_Load(object sender, EventArgs e)
    {

        lblTime.Text = DateTime.Now.ToString();
        // this will add callback method. so method defined here will be called every time before cache data is loded.
        // so in this method, we can decide whether to load previously cache page(VALID) or remove cache and load page again (INVALIDATING cache).
        Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(MycacheValidate), null);

    }

    public static string GetTime(HttpContext context)
    {

        return DateTime.Now.ToString();
        
    }

    // this method will be run every time before caching. to check cache status whether to cache page or not ??
    public static void MycacheValidate(HttpContext context,Object data, ref HttpValidationStatus vStatus)
    {
        //you can use quary string here, and decide cache behaviour

        vStatus = HttpValidationStatus.Invalid; // remove cache. load whole page
        //vStatus = HttpValidationStatus.Valid;   // dont invalidate. cache it ok.
        //vStatus = HttpValidationStatus.IgnoreThisRequest;  // not cache in currunt request.ignore it. will cache next requests.

    }
}

Notice that this code sample uses logic to specify one of the HttpValidationStatus values to
control how the page is cached:

 HttpValidationStatus.Invalid This causes the cache to be invalidated so that the page
is dynamically generated. The newly generated page is stored in the cache, replacing
the earlier cached version

HttpValidationStatus.Ignore ThisRequest This causes the current page request to
be dynamically generated without invalidating the previously cached version of the
page. The dynamically generated page output is not cached, and future requests
might receive the previously cached output.

■ HttpValidationStatus.Valid This causes ASP.NET to return the cached page.