Thursday, February 27, 2014

System.Runtime.Caching

Scenario

Continue from the previous post, the objective of my research is to find out a cache facility replacement for ASP.NET cache. The reason is when we use ASP.NET caching in WCF application, we are required to configure and turn on AspNetCompatibilityEnabled for your WCF service and that would deteriorate your WCF performance. Therefore, we want to avoid that happen by not having ASP.NET caching use in WCF.

AppFabric caching is one of the options, but it is overkill for a small-medium size application. Enterprise Library Caching Application Block is another option, however, I find that the latest Enterprise Library 6.0 no longer having Caching Application Block, checkout this article. From there, you will notice that Caching Application Block has been retired and replaced by System.Runtime.Caching classes which is available in .NET 4.0.

Implementation

In order to use the runtime caching in your application, go to your project and open up the "Add Reference" dialog, and then locate System.Runtime.Caching.


The main class library is MemoryCache, you can use the default cache engine when you start your application with the following code.

private static MemoryCache _cache;

static Program()
{
    _cache = MemoryCache.Default;

}

However, if you wish to use own custom cache engine, you can create your own custom caching provider by implementing the abstract ObjectCache.

Now, you may start playing around with the cache by stuffing object into it by using the MemoryCache Add or Set method. Add method is used to add cache item when there is no item in the cache. Set method is used if you want it to add item if it does not exist or replace item if it already exists.

private static void InitializeCache()
{
    //CountryList is my cache key name
    CacheItem cacheItem = new CacheItem("CountryList");
           
    List<Country> countries = new List<Country>();
    countries.Add(new Country() { ID = 1, Value = "Malaysia" });
    countries.Add(new Country() { ID = 2, Value = "Singapore" });
    countries.Add(new Country() { ID = 3, Value = "Thailand" });
    countries.Add(new Country() { ID = 4, Value = "Indonesia" });

    cacheItem.Value = countries;

    CacheItemPolicy cachePolicy = new CacheItemPolicy();

    //NOTE: Only can use/choose one between AbsoluteExpiration or SlidingExpiration
    //Absolute expiration mean clear cache after specific time
    cachePolicy.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(10);

    //Sliding expiration mean clear cache if it has not been used after specific time
    //cachePolicy.SlidingExpiration = new TimeSpan(0, 5, 0); //5 mins

    //Priority Not Removable if you do not want the cache to be cleared
    cachePolicy.Priority = CacheItemPriority.NotRemovable;

    //NOTE: Only can use one UpdateCallback or RemovedCallback.
    //Fire the OnCacheUpdated event once the cache item has been modified
    //cachePolicy.UpdateCallback += OnCacheUpdated;

    //Fire the OnCacheRemoved event once the cache item has been removed
    cachePolicy.RemovedCallback += OnCacheRemoved;

    //Stuff the cache item and cache policy into the cache
    _cache.Set(cacheItem, cachePolicy);
}

When you use both AbsoluteExpiration and SlidingExpiration, you would get the following error:
AbsoluteExpiration must be DateTimeOffset.MaxValue or SlidingExpiration must be TimeSpan.Zero.

When you use both UpdateCallback and RemovedCallback, you would get the following error:
Only one callback can be specified.  Either RemovedCallback or UpdateCallback must be null.

The following are the callback method implementation:

private static void OnCacheRemoved(CacheEntryRemovedArguments arguments)
{
    Console.WriteLine("Somebody changed my cache! Or cache item evicted!");
    Console.WriteLine("Cache Item Removed - Key: " + arguments.CacheItem.Key);
    Console.WriteLine("Reason: " + arguments.RemovedReason.ToString());

    //Get the object which was removed.
    List<Country> countries = (List<Country>)arguments.CacheItem.Value;

    //Do what you want here after cache item is removed.
}

private static void OnCacheUpdated(CacheEntryUpdateArguments arguments)
{
    Console.WriteLine("Somebody changed my cache! Or cache item evicted!");
    Console.WriteLine("Cache Item Updated - Key: " + arguments.Key);

    //Get the object which was updated.
    List<Country> countries = (List<Country>)arguments.UpdatedCacheItem.Value;

    //Do what you want here after cache item is updated.

}

Now, you can play around with your cache item like updating or removing it, then it should fire the callback event which you had registered.

Change Monitor

The runtime cache also support change monitors which can hook up with the CacheItem callback events. There are 2 change monitors which are already available in the System.Runtime.Caching library:

  1. SqlChangeMonitor
  2. HostFileChangeMonitor
So, imagine that you have loaded your cache with the data from your database, in the mean time, you want your cache data always up to date base on the data in the database. You can use SqlChangeMonitor to monitor the database data change, then rely on SqlDependency to trigger the cache callback event if it detect changes. For more information how to implement this SqlChangeMonitor, please visit this great blog post.


For HostFileChangeMonitor, it is used to monitor any of your text file. If you cache data come from a text file, and if there is any change to the monitored text file, HostFileChangeMonitor will automatically trigger the cache callback event. Then, you can refresh your cache data by re-reading the text file.

So, here is how you use the change monitor:

CacheItemPolicy cachePolicy = new CacheItemPolicy();
HostFileChangeMonitor monitor = new HostFileChangeMonitor(new string[1] { "D:\\test.txt" });

cachePolicy.ChangeMonitors.Add(monitor);

Summary

System.Runtime.Caching class library is meant to provide caching facility for non web projects. Imagine we are still using ASP.NET caching, it is weird to have System.Web.dll reference in your non web project. Few years ago before .NET 4.0 was released and System.Runtime.Caching was not available yet, we have limited options and could only rely on 3rd party caching facility such as Enterprise Library.

This new cache also provide the somehow similar feature SqlCacheDependency which available in ASP.NET cache as the SqlChangeMonitor. And, a new feature with HostFileChangeMonitor which is not available in ASP.NET cache.

If you are interested with my source code, feel free to download it from HERE.







3 comments:

  1. Nice article..

    But I have found another simple example to call a WCF RestFul Service using jQuery AJAX Call, please refer to link below:-
    http://www.etechpulse.com/2014/03/consume-restful-wcf-service-in-aspnet.html
    http://www.etechpulse.com/2014/03/how-to-consume-wcf-restful-service-in.html

    Thanks

    ReplyDelete
    Replies
    1. Nice blog, is that your blog? Anyway, I have a similar post too:
      http://sylvester-lee.blogspot.com/2013/04/wcf-rest-service-httpclient-vs-wcf.html

      Thanks.

      Delete
  2. By the by, IT-circle assumes an extremely critical part in the Spanish economy. IT arrangements have previously tracked down their applications in numerous circles of public life in this country. For instance, such developments are utilized in street traffic signal, as per the MIT Innovation Survey. Giving electronic ID cards additionally became normal there, and Spain was the principal country in Europe to execute this training. It likewise puts this area to the highest point of electronic marks use. Computerized advancements are additionally acknowledged in the circle of general wellbeing, so most medical services foundations utilize electronic types of the clinical history of patients. IT arrangements act as a reason for e-banking where the primary consideration is paid to the security of installments given by the clients>> Mobilunity

    ReplyDelete

Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...