Click here to Skip to main content
Click here to Skip to main content

WCF Cache

, 9 Dec 2009
Rate this:
Please Sign up or sign in to vote.
A WCF Service caching example.

caching_enabled_20s.JPG

Introduction

In this article, I’ll discuss caching in WCF services, and I’ll demonstrate how WCF caching can be implemented.

Source Code

The source code contains two Windows applications. The first hosts a demo WCF service. The second application is the WCF demo client. The solution also contains the WCFCache class I wrote that allows you to easily add caching features to WCF services or any other type of application. For running the code, you’ll need the AdventureWorks database that can be downloaded here. Also, you’ll need to update the connection string in the configuration file of the WCF server with the required values.

WCF Caching

Caching in WCF, if used wisely, is definitely a good thing. Lets say that you have a method in your service that executes expensive queries, and this method is called very often, there is a big percentage of calls that pull the same data, the resulting data is not too big to be stored in memory (if, of course, it’s going to be stored in memory), and the data can be considered valid for a period of time, then this is the perfect place to use some sort of caching.

How can caching be added to WCF? You can implement a custom solution like this one, you can use some third party components, or you can use the System.Web.Caching.Cache class. I don’t recommend the last one because I have never tried using it in this context. I found different opinions on the web about this. For me, the fact that Microsoft explicitly recommends not to do it was enough reason not to use it: “The Cache class is not intended for use outside of ASP.NET applications. It was designed and tested for use in ASP.NET to provide caching for Web applications. In other types of applications, such as console applications or Windows Forms applications, ASP.NET caching might not work correctly.” http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx.

A typical data access method that uses caching executes the following two general steps: Checks the cache for the existence of the requested data and returns the data if found. If the data is not found in the cache, then it pulls it from the data store, stores it in the cache, and returns the data.

Also, you have to take care of removing or updating data in the cache under certain conditions. Usually, this is done when the data is no longer valid (was changed, or it wasn’t updated for too long), or the data was not used for too long.

Using the WCFCache class

The class was designed to provide similar functionality as System.Web.Caching.Cache. The class is used through its static properties. It allows you to add or remove items from the cache. It has the possibility to indicate item expiration time and/or sliding expiration time. Below are some examples of using the class:

//add/update an item to the cache. No expiration date. No sliding expiration time.
WCFCache.Current[productID] = product;

//add/update an item in the cache.
//The item will expire in 2 minutes. No sliding expiration time.
WCFCache.Current.Insert(productID, product, DateTime.Now.AddMinutes(2));

//add/update an item to the cache. No expiration date. 
//Expiration sliding time is 30 seconds.
WCFCache.Current.Insert(productID, product, new TimeSpan(0, 0, 30), true);

//get an item from the cache
product = (Product)WCFCache.Current[productID]

//change cache refresh frequency. Default value is 20 seconds.
//This means each 20 seconds the cache is inspected for expired items.
WCFCache.Current.CacheRefreshFrequency = new TimeSpan(0,0,10);

Now, let’s discuss a little on how it was implemented. Internally, the data is stored in a hash table for faster access. To make the class thread safe, I used the ReaderWriterLockSlim class. ReaderWriterLockSlim allows multiple threads for reading and exclusive access for writing. Below is how one of the overloaded versions of the Insert method was implemented:

public void Insert(object key, object value)
{
    _itemsLock.EnterWriteLock();
    try
     {
          _items[key] = new WCFCacheItem(value);
      }
      finally
      {
          _itemsLock.ExitWriteLock();
      }
}

where _itemsLock is ReaderWriterLockSlim and _items is the hash table.

For inspecting the cache for expired items, I used System.Threading.Timer.

Code Testing

For the purpose of testing the class, I created a WCF service and WCF client, both in the form of Windows applications. The client creates a number (it’s configurable from the UI) of threads on start. Each thread will pick a random product ID and try to get the data from the server on that product. On the server side, there are two methods exposed. One for getting the initial list of products IDs and another to get data on a particular product. Only the second method uses caching. Caching can be disabled or enabled in the server UI. Also, the sliding expiration time for the created cached items can be specified. Below are the results of running the test for 5 minutes with caching enabled:

caching_enabled_40s.JPG

and caching disabled:

caching_disabled.JPG

As you can see, the average call time with cache enabled was 78 milliseconds, and with cache disabled was 528 milliseconds. If the query for getting the product would run longer, then the difference would be correspondingly bigger.

Conclusion

Thank you for reading. I hope this was useful to you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Alexandru Cibotari
Web Developer
Canada Canada
No Biography provided

Comments and Discussions

 
QuestionWhere is the cache persisted? PinmemberCarl Reid29-Jul-11 6:02 
I know this is an old article however I only read it today so apologies.
 
Your article is interesting however you have not explained where the caching occurs. You mention that you use a hashtable but where is this hash table actually persisted?
 
WCF services are stateless and since there is no application cache I cannot see what state mechanism you are using to store the items in the cache.
 
Perhaps this is explained in the source code however IMHO it should also be explained in the article since this is a very important part of the overall solution, if not the most important part!
 
Thanks
AnswerRe: Where is the cache persisted? PinmemberAlexandru Cibotari29-Jul-11 7:19 
GeneralRe: Where is the cache persisted? PinmemberCarl Reid1-Aug-11 2:32 
GeneralRe: Where is the cache persisted? PinmemberAlexandru Cibotari2-Aug-11 6:12 
QuestionDid you consider using the Caching block from the Enterprise library? PinmemberTobias Manthey10-Jan-10 23:22 
AnswerRe: Did you consider using the Caching block from the Enterprise library? PinmemberAlexandru Cibotari11-Jan-10 4:29 
Generalnice work PinmemberJon Smith 037414-Dec-09 6:32 
GeneralMy vote of 1 PinmemberRamon Smits10-Dec-09 12:01 
QuestionWhat kind of caching? PinmemberRamon Smits10-Dec-09 12:01 
GeneralSample is not working.,.Throwing error.,. PinmemberSrinath G Nath9-Dec-09 19:45 
GeneralRe: Sample is not working.,.Throwing error.,. PinmemberAlexandru Cibotari9-Dec-09 23:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140821.2 | Last Updated 10 Dec 2009
Article Copyright 2009 by Alexandru Cibotari
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid