Introduction
In this article, you will learn some solutions about local data caching in ASP.NET Web Application .
Why Is Local Data Caching Important ?
Maybe some of you will ask me this question : "Why don't you use the distributed caching to substitute for the local caching , such as Redis and Memcached ? "
Here is my answer:
Handling Multi-Level Caching!
There is no doubt that I will use distributed caching , but I don't use only distributed caching for my designer. I will use local caching as my first-level data caching and distributed caching as my second-level data caching . Only one level data caching may not very good for the caching component!
Network connection and serialization will also cost some time when using the distributed caching . Some data we may use frequently then others at other times, otherswill do better than distributed caching. We need to care more when we use caching!
There are also some differences when using local caching between traditional ASP.NET web application and ASP.NET Core web application . In this article, I will show you the traditional ASP.NET web application , next time will show ASP.NET Core web application.
In .NET Framework web application , we often use two types of local caching : System.Web.Caching and MemoryCache .
System.Web.Caching
When we use this type of caching , two have two choices:
- HttpRuntime.Cache
- HttpContext.Cache
Both HttpRuntime.Cache and HttpContext.Cache are the instance of System.Web.Caching.Cache . So you can find lots of commons when you use them . You can choose one of them based on your hobbies . And my suggestion is to choose HttpRuntime.Cache !
We need to use Insert method to save the data. The following code demonstrates a simple sample for storing data to caching :
- HttpRuntime.Cache.Insert("yourkey",new object());
You may notice that the above code doesn't set the expiration of this caching item. It means that this caching item will not be destroyed until this web application is stopped or restarted. In this scenario , we may store some unchanged items , such as areas .
However , I don't suggest you set the expiration . It may cause unnecessary costs of the RAM , what we need to do is to set a sliding expiration of data.
We will continue with the expiration when we save the data .
There are two types of expiration , one is sliding expiration , the other one is absolute expiration . And we can only use one type for a caching item.
If we want to set a sliding expiration for caching items, we can do so like this,
- HttpRuntime.Cache.Insert("yourkey"
- ,obj
- ,null
- ,Cache.NoAbsoluteExpiration
- ,TimeSpan.FromMinutes(1));
If we want to set an absolute expiration for caching items, we can do so like this,
- HttpRuntime.Cache.Insert("yourkey"
- ,obj
- ,null
- ,DateTime.UtcNow.AddMinutes(10)
- ,Cache.NoSlidingExpiration);
The following table shows you the relation between expiration properties and equivalent values.
Expiration Property | Equivalent Value |
System.Web.Caching.Cache.NoAbsoluteExpiration | DateTime.MaxValue |
System.Web.Caching.Cache.NoSlidingExpiration | TimeSpan.Zero |
Turning to getting the caching item .
- var res = HttpRuntime.Cache.Get("mykey");
It's very easy to get the data from caching. We only pass the caching key when we call the method .
Sometimes , we need to remove the caching item for some reason, at this time , we can use the Remove method to remove the caching item.
- HttpRuntime.Cache.Remove("mykey");
MemoryCache
We can use MemoryCache to handle caching as well. But MemoryCache only supports .NET 4.0 or higher.
Before we use the MemoryCache , we need to add the reference System.Runtime.Caching at first .
We need to get the instance of it . We often use MemoryCache.Default.
- private MemoryCache cache = MemoryCache.Default;
Storing data at first as well.
When we store something via MemoryCache , we must set the expiration.
Sample with absolute expiration.
- cache.Set("mykey",obj,DateTimeOffset.UtcNow.AddSeconds(10));
Sample with sliding expiration .
We need to use CacheItemPolicy to configure the sliding expiration. You also can set the absolute expiration through CacheItemPolicy as well .
- var cacheItem = new CacheItem("mykey", obj);
- var cacheItemPolicy = new CacheItemPolicy
- {
- SlidingExpiration = TimeSpan.FromSeconds(60 * 2) ,
-
- };
- cache.Set(cacheItem, cacheItemPolicy);
The usages of getting caching item and removing caching item in MemoryCache are the same as System.Web.Caching .
Get caching item .
- var res = cache.Get("mykey");
Remove caching item .
Furthermore , when using MemoryCache , we can store caching items in different regions. This is a very good feature.
The following code demonstrates the usages of MemoryCache with region.
-
- cache.Set("mykey"
- ,obj
- ,DateTimeOffset.UtcNow.AddSeconds(10)
- ,"region_1");
-
-
- var cacheItem = new CacheItem("mykey", obj,"region_2");
- var cacheItemPolicy = new CacheItemPolicy
- {
-
- AbsoluteExpiration = DateTimeOffset.UtcNow.AddSeconds(10)
- };
- cache.Set(cacheItem, cacheItemPolicy);
-
-
- var res = cache.Get("mykey","region_2");
-
-
- cache.Remove("mykey","region_1");
Above two solutions is the most frequent we use ! But there also has another way to do this job! We can use the In-Memory database to that as well !
In-Memory Database
For this solution , not only we can use in traditional .NET Framework projects , but also emerging .NET Core projects.
In-Memory database can help us to handle different types of applications, but it still costs times to query data from database , so it will perform slower than the above two solutions.
How can we use SQLite to do this work ? Here I will design a simplest SQLite caching component by some T-SQL commands.
First of all , we need to create a table to store the caching items. We need three columns for this table: CacheKey , CacheValue and the UinxTimestamp .
The following table explains those fields .
Field | Description |
CacheKey | key of the caching item |
CacheValue | a serialized value of the caching item |
UinxTimestamp | timestamp to store the absolute expiration(UTC time here) |
When we store the caching item , we will insert a record to the table .
- INSERT INTO yourtable(cachekey,cachevalue,absoluteexpiration) VALUES('mykey'
- ,'myvalue'
- ,(SELECT datetime('now', 'unixepoch'))+10000)
When we get data from caching , we will query a record from table
- SELECT cachevalue FROM yourtable
- WHERE cachekey='mykey'
- AND uinxiimestamp > datetime('now', 'unixepoch');
When we want to delete the caching , we should delete the record from database .
- DELETE FROM [yourtable]
- WHERE [cachekey] = 'mykey'
By the way , if we want to delete all of the expired caching ,we can use the following command to remove.
- DELETE FROM [yourtable]
- WHERE [uinxiimestamp] < strftime('%s','now')
Furthermore, here is a simple component for SQLite caching you will find more details on my Github page.
Summary
In this article, I showed you three solutions to handle local data caching in your web application . And showed you my view on the importance of local data caching . You can choose one of the above solutions based on your scenario when you use local data caching .