Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Reloading or refreshing cache automatically, when cached data is removed - Part 130

Suggested Videos
Part 127 - Different ways to cache application data in asp.net
Part 128 - AbsoluteExpiration, SlidingExpiration, and CacheItemPriority
Part 129 - Cache dependency on files

In this video we will discuss about
1. When and how to use "CacheItemRemovedCallback" delegate
2. Reloading or refreshing cache automatically, when cached data has expired



Create an asp.net web application. Copy and paste the following HTML on WebForm1.aspx.
<div style="font-family: Arial">
    <asp:Button ID="btnLoadCountriesAndCache" runat="server" Text="Load Countries & Cache"
        OnClick="btnLoadCountriesAndCache_Click" />
    &nbsp;
    <asp:Button ID="btnGetCountriesFromCache" runat="server" Text="Get Countries from Cache"
        OnClick="btnGetCountriesFromCache_Click" />
    <br />
    <br />
    <asp:GridView ID="gvCountries" runat="server">
    </asp:GridView>
    <br />
    <asp:Button ID="btnRemoveCachedItem" runat="server" Text="Remove Cached Item" 
    OnClick="btnRemoveCachedItem_Click" />
    &nbsp;
    <asp:Button ID="btnGetCacheStatus" runat="server" Text="Get Cache Status" 
    OnClick="btnGetCacheStatus_Click" />
    <br />
    <br />
    <asp:Label ID="lblMessage" Font-Bold="true" runat="server"></asp:Label>
</div>



Copy and paste the following code in WebForm1.aspx.cs
protected void btnLoadCountriesAndCache_Click(object sender, EventArgs e)
{
    // Load countries data from XML file into dataset
    DataSet ds = new DataSet();
    ds.ReadXml(Server.MapPath("~/Data/Countries.xml"));

    // Create an instance of CacheItemRemovedCallback delegate. Notice that this delegate
    // points to CacheItemRemovedCallbackMethod. When cache item is removed 
    // for any   reason
    // the delegate gets invoked, which in turn will invoke the method it is pointing to.
    CacheItemRemovedCallback onCacheItemRemoved = 
       new CacheItemRemovedCallback(CacheItemRemovedCallbackMethod);

    // Cache countries dataset. Please note that we are passing the delegate instance as an
    // argument for CacheItemRemovedCallback delegate parameter of the insert() method.
    Cache.Insert("CountriesData", ds, new CacheDependency(Server.MapPath("~/Data/Countries.xml")), DateTime.Now.AddSeconds(60),
        System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, onCacheItemRemoved);
            
    // Set the dataset as the datasource for the gridview
    gvCountries.DataSource = ds;
    gvCountries.DataBind();
    lblMessage.Text = ds.Tables[0].Rows.Count.ToString() + " rows retrieved from XML file.";
}

protected void btnGetCountriesFromCache_Click(object sender, EventArgs e)
{
    // Check if countries dataset exists in cache
    if (Cache["CountriesData"] != null)
    {
        // If countries dataset is in cache, retrieve it
        DataSet ds = (DataSet)Cache["CountriesData"];
        // Set the dataset as the datasource
        gvCountries.DataSource = ds;
        gvCountries.DataBind();
        // Retrieve the total rows count
        lblMessage.Text = ds.Tables[0].Rows.Count.ToString() + " rows retrieved from cache.";
    }
    else
    {
        lblMessage.Text = "Cache item with key CountriesData is not present in cache";
    }
}

protected void btnRemoveCachedItem_Click(object sender, EventArgs e)
{
    // Remove cached item explicitly
    Cache.Remove("CountriesData");
}

// This method gets invoked automatically, whenever the cached item is removed from cache
public void CacheItemRemovedCallbackMethod(string key, object value, CacheItemRemovedReason reason)
{
    // Retrieve the key and reason for removal
    string dataToStore = "Cache item with key = \"" + key + "\" is no longer present. Reason = " + reason.ToString();
    // Cache the message
    Cache["CacheStatus"] = dataToStore;

    // ADO.NET code to store the message in database
    // string cs = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
    // SqlConnection con = new SqlConnection(cs);
    // SqlCommand cmd = new SqlCommand("insert into tblAuditLog values('" + dataToStore + "')", con);
    // con.Open();
    // cmd.ExecuteNonQuery();
    // con.Close();

    // Reload data into cache
    // DataSet ds = new DataSet();
    // ds.ReadXml(Server.MapPath("~/Data/Countries.xml"));

    // CacheItemRemovedCallback onCacheItemRemoved = new CacheItemRemovedCallback(CacheItemRemovedCallbackMethod);
    // Cache.Insert("CountriesData", ds, new CacheDependency(Server.MapPath("~/Data/Countries.xml")), DateTime.Now.AddSeconds(60),
    //    System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, onCacheItemRemoved);
}

protected void btnGetCacheStatus_Click(object sender, EventArgs e)
{
    if (Cache["CountriesData"] != null)
    {
        lblMessage.Text = "Cache item with key \"CountriesData\" is still present in cache";
    }
    else
    {
        if (Cache["CacheStatus"] != null)
        {
            lblMessage.Text = Cache["CacheStatus"].ToString();
        }
    }
}

Explanantion of code in btnLoadCountriesAndCache_Click() event handler:
When you click "Load Countries & Cache" button, the xml data is read from "Countries.xml" into a dataset, which is then cached. Notice that, before we cache data using the "Cache" objects "Insert()" method, we are creating an instance of CacheItemRemovedCallback delegate. To the constructor of this delegate, we are passing, the name of the function that we want to have executed automatically, when the cache item is removed from cache. An item may be removed, from cache, when any of the following conditions are true
1. The cached item has expired.
2. The cache is full.
3. There is a cache dependency, and the item, that the cache object is dependent on has changed.
4. The cache item may also be explicitly removed using Cache object's Remove() method.

The delegate object is then passed as an argument for CacheItemRemovedCallback delegate parameter of the insert() method. So, when the item, with cache key="CountriesData" is removed the delegate gets invoked, which in turn will automatically invoke, the function it is pointing to, in our case "CacheItemRemovedCallbackMethod()".

Explanantion of code in CacheItemRemovedCallbackMethod() function:
This method gets invoked automatically, whenever the cached item is removed from cache. So, this is the opportunity for us to decide what we want to do when the cached item is removed from cache. For example, in this method the following 2 lines get the key of the item that is removed from the cache and the removed reason, and stores the message in another cache object, with key="CacheStatus".
string dataToStore = "Cache item with key = \"" + key + "\" is no longer present. Reason = " + reason.ToString();
Cache["CacheStatus"] = dataToStore;

Alternatively we can also store information about the removed cache object, in a database table. The ado.net code that does this is commented.

Finally we can also reload data ino cache, from the XML file. The code to reload data into cache, is also commented.

Explanantion of code in btnGetCountriesFromCache_Click() event handler:
The code in "Get Countries from Cache" button click event handler is straight forward. We check if countries data is present in cache, and if it is, we retrieve the data from cache and display in gridview control.

Code in btnRemoveCachedItem_Click() and btnGetCacheStatus_Click() is self explanatory.

1 comment:

  1. Hai Venkat sir.The CacheItemRemovedCallbackMethod is working fine while retrieving data from XML Datasource ,if there is any change in the XML file for ex: Xml data value China changed to China2, it is loading the gridview with the updated data.This is working fine in VS2012 and other earlier versions But When I tried the same in VS2013,It is giving a error: Cache item with key CountriesData is not present in cache. Please explain why this is happening??..

    ReplyDelete

It would be great if you can help share these free resources