Since ASP.NET first came, it came up with a very powerful feature of in-memory object cache (System.Web.Caching.Cache
) to store commonly used expensive data on server side. Almost every ASP.NET application/site uses this feature now. But it suffers from few shortcomings like:
- It is available in ASP.NET only leaving WinForms or WPF clients puzzled.
- It is not extensible to accommodate other demands to store cache objects in disk or SQL Server. However, Microsoft after realizing these shortcomings, Caching Application Block library was included in its Enterprise Library.
- .NET developers have to look for their own mechanisms to create logical in-memory partitions called regions to group or organize cache objects in memory.
However, .NET 4.0 came up with a new set of caching APIs in System.Runtime.Caching namespace that addresses all the above shortcomings. This new namespace can be found in System.Runtime.Caching.dll assembly. But this assembly reference is available only in the target framework of .NET Framework 4, not .NET Framework 4 Client Profile.
The System.Runtime.Caching
namespace contains two core sets of classes:
- The concrete implementation of System.Runtime.Caching.MemoryCache class supports in-memory object cache.
MemoryCache
is closely modeled after old System.Web.Caching.Cache
of ASP.NET. However, one does not have to rely upon System.Web
assembly to use MemoryCache
(We will see it through an example shortly). Abstract
types to build custom cache implementation other than in-built MemoryCache
.
Now let’s move to try out an example to leverage MemoryCache
features. First of all, we will create a class library type project. Add a class MyCache
and assembly reference of System.Runtime.caching.dll.
MyCache Code Sample
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Caching;
namespace DotNetCachingWrapper
{
public enum MyCachePriority
{
Default,
NotRemovable
}
public class MyCache
{
private static ObjectCache cache = MemoryCache.Default;
private CacheItemPolicy policy = null;
private CacheEntryRemovedCallback callback = null;
public void AddToMyCache(String CacheKeyName, Object CacheItem,
MyCachePriority MyCacheItemPriority, List<String> FilePath)
{
callback = new CacheEntryRemovedCallback(this.MyCachedItemRemovedCallback);
policy = new CacheItemPolicy();
policy.Priority = (MyCacheItemPriority == MyCachePriority.Default) ?
CacheItemPriority.Default : CacheItemPriority.NotRemovable;
policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.00);
policy.RemovedCallback = callback;
policy.ChangeMonitors.Add(new HostFileChangeMonitor(FilePath));
cache.Set(CacheKeyName, CacheItem, policy);
}
public Object GetMyCachedItem(String CacheKeyName)
{
return cache[CacheKeyName] as Object;
}
public void RemoveMyCachedItem(String CacheKeyName)
{
if (cache.Contains(CacheKeyName))
{
cache.Remove(CacheKeyName);
}
}
private void MyCachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), "
| Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ",
arguments.CacheItem.Value.ToString());
}
}
}
Build this class library to generate assembly name of MyCachingWrapper.dll. Now we are ready to use this library in all ASP.NET web, WinForms and WPF applications.
Now let’s see examples of how this library can be commonly used in both ASP.NET Web Form and WinForm after adding reference of MyCachingWrapper.dll.
ASP.NET Page_Load
protected void Page_Load(object sender, EventArgs e)
{
MyCache objCache = new MyCache();
String strUserName = objCache.GetMyCachedItem("USER_NAME") as String;
if (String.IsNullOrEmpty(strUserName))
{
List<String> lstFiles = new List<string>();
lstFiles.Add(HttpContext.Current.Request.MapPath("~/XmlFiles/ListOfUsers.xml"));
XElement x = XElement.Load(HttpContext.Current.Request.MapPath
("~/XmlFiles/ListOfUsers.xml"));
var qry = from u in x.Elements("Users") where
u.Element("UserCode").Value == "101" select u;
strUserName = qry.First().Element("UserName").Value;
objCache.AddToMyCache("USER_NAME", strUserName, MyCachePriority.Default, lstFiles);
}
this.lblUserName.Text = strUserName;
}
WinForm Form_Load
private void frmDefault_Load(object sender, EventArgs e)
{
MyCache objCache = new MyCache();
String strFilePath =System.IO.Path.Combine(Environment.CurrentDirectory,
"../../XmlFiles/ListOfUsers.xml");
String strUserName = objCache.GetMyCachedItem("USER_NAME") as String;
if (String.IsNullOrEmpty(strUserName))
{
List<String> lstFiles = new List<string>();
lstFiles.Add(strFilePath);
XElement x = XElement.Load(strFilePath);
var qry = from u in x.Elements("Users") where
u.Element("UserCode").Value == "101" select u;
strUserName = qry.First().Element("UserName").Value;
objCache.AddToMyCache("USER_NAME", strUserName, MyCachePriority.Default, lstFiles);
}
this.lblUserName.Text = strUserName;
}
Sample ListOfUsers.xml File
="1.0"
<ListOfUsers xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Users>
<UserCode>101</UserCode>
<UserName>Dan Brown</UserName>
</Users>
<Users>
<UserCode>102</UserCode>
<UserName>da Vinci</UserName>
</Users>
<Users>
<UserCode>103</UserCode>
<UserName>Monalisa</UserName>
</Users>
<Users>
<UserCode>104</UserCode>
<UserName>Shakespeare</UserName>
</Users>
<Users>
<UserCode>105</UserCode>
<UserName>William Wordsworth</UserName>
</Users>
</ListOfUsers>
Now we can debug the above code and see other interesting things. You will see the usage of MemoryCache
methods and its techniques to cache objects are similar to what we have been doing in ASP.NET cache so far. Also, we see how the same MyCache
library is usable in both web and windows applications.
MemoryCache Points Worth Mentioning
Hope all of you will appreciate the .NET 4.0 caching feature.
CodeProject
Filed under:
.Net Technologies,
ASP.Net,
C#/VB.Net,
CodeProject,
Dot Net Tips,
MemoryCache,
ObjectCache Tagged:
.Net 4.0,
ASP.Net,
C#,
Caching,
MemoryCache,
ObjectCache,
Visual Studio 2010