Introduction
Caching is a process for storing frequently accessed data/information in memory, so that, when the same data/information is needed the next time, it could then be directly retrieved from the memory instead of being generated by the application.
Caching is one of the most important factor in creating a high-performance, scalable web application.
ASP.NET provides the following types of caching:
- Output Caching – Output cache stores a copy of the finally rendered HTML pages or part of the pages sent to the client. When the next client requests the same page, instead of regenerating the page, a cached copy of the page is sent, thus saving time.
- Data Caching – Data caching means caching data from a data source. As long as the cache is not expired, a request for the data will be fulfilled from the cache. When the cache is expired, fresh data is obtained by the data source and the cache is refilled.
- Object Caching – Object caching is caching the objects on a page, such as data-bound controls. The cached data is stored in the server’s memory.
- Class Caching – Web pages or web services are compiled into a page class in the assembly, when run for the first time. Then the assembly is cached in the server. The next time when a request is made for the page or service, the cached assembly is referred to. When the source code is changed, the CLR recompiles the assembly.
- Configuration Caching – Application-wide configuration information is stored in a configuration file. Configuration caching stores the configuration information in the server memory.
This document intends to provide a generic cache helper class in C# to implement and use data caching in ASP.NET web applications.
Cache Helper Class (CacheHelper.cs)
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Caching;
namespace WebApplication1.Helper {
public class CacheHelper {
const double DefaultExpirationMins = 1440; //1 Day
/// <summary>Adds the specified value at the specified key in the cache, with no sliding expiration and default expiry (1 day)</summary>
/// <typeparam name=”T”>the type of value</typeparam>
/// <param name=”key”>the cache key</param>
/// <param name=”value”>the object to cache</param>
public static void Set < T > (string key, T value) {
if (string.IsNullOrWhiteSpace(key) || value == null)
return;
HttpContext.Current.Cache.Insert(key, value, null,
DateTime.Now.AddMinutes(DefaultExpirationMins), Cache.NoSlidingExpiration);
}
///<summary>Adds the specified value at the specified key in the cache, with no sliding expiration and default expiry (1 day) </summary>
/// <typeparam name=”T”>the type of value</typeparam>
/// <param name=”key”>the cache key</param>
/// <param name=”value”>the object to cache</param>
/// <param name=”expirationInMinutes”>the cache expiration, in minutes</param>
public static void Set < T > (string key, T value, double expirationInMinutes) {
HttpContext.Current.Cache.Insert(key, value, null,
DateTime.Now.AddMinutes(expirationInMinutes),
Cache.NoSlidingExpiration);
}
/// <summary>Gets whether the specified key exists in the cache</summary>
/// <param name=”key”>the cache key</param>
/// <returns>True if the key exists, otherwise false</returns>
public static bool Exists(string key) {
return HttpContext.Current.Cache[key] != null;
}
/// <summary>Removes the specified key and associated object from the cache</summary>
/// <param name=”key”>the cache key to remove</param>
public static void Remove(string key) {
HttpContext.Current.Cache.Remove(key);
}
/// <summary>Gets the cached object associated with the provided key</summary>
/// <typeparam name=”T”>Type of cached item</typeparam>
/// <param name=”key”>Name of item</param>
/// <param name=”value”>the cached item</param>
/// <returns>True if the cached item is retrieved, otherwise False</returns>
public static bool Get < T > (string key, out T value) {
try {
if (Exists(key)) {
value = (T) HttpContext.Current.Cache[key];
return true;
}
} catch (InvalidCastException) { //TODO: Handle exceptions accordingly
}
value =
default (T);
return false;
}
/// <summary> Gets the cached object with the provided key if it exists
/// or executes the getter func, caches the result and returns it.
/// </summary>
/// <typeparam name=”T”>Type of cached item</typeparam>
/// <param name=”key”>Name of item</param>
/// <param name=”getter”>the func to execute if key does not exist in the Cache</param>
/// <returns>the cached item associated with the key</returns>
public static T GetOrSet < T > (string key, Func < T > getter) {
T value;
if (!Exists(key) || !Get(key, out value)) {
value = getter();
Set(key, value);
}
return value;
}
}
}
Usage
After adding the CacheHelper class to your application, simply call the associated methods of the class.
Most of the methods of the cache helper class are self-explanatory and their usage is trivial.
Below is the usage for Set and Get methods
Example:
//Assigning the value to cache based on key int UserId = 1000; //adding Userid as key to the cache as interger type CacheObject.Set < int > ("UserId", UserId);
//Getting the value from cache based on given key
int UserId = CacheObject.Get < int > (“UserId”);
Here we can set a model or list of data and get the same.
Example for the GetOrSet method:
It takes a function as an argument to retrieve the cached object from data base or any other source, if it doesn’t exist in the cache.
For simplicity, the example below uses Entity Framework’s DbContext class for data access, which is passed as an argument to the methods.
public List < UserRoles > GetRoles(DbContext dbContext) { return CacheHelper.GetOrSet("UserRolesCacheKey", () => GetUserRoles(dbContext)); //Method to get roles from DB
}
Conclusion
Caching is one of the most important strategies in improving application performance especially web and mobile applications. With responsive user experience, caching can provide a significant overall improvement in an application’s perceived response time.
As with any other performance improvement mechanism, ensure you thoroughly load test and profile your web application both before and after caching.