When it comes to storing data, .NET developers have a veritable arsenal at their disposal. Aside from the
System.IO namespaces, ASP.NET developers can store data in 5 main places:
Context. Each of these mechanisms have their own unique characteristics and uses. The main thing which separates most of them is their scope - some are long lived, some are short live, some are shared amongst all site users, others aren't.
In most cases, it's pretty clear when to use the
Context objects (although the
Context object is generally underused by developers). It's also clear when data should be available to all users (Application) or is user-specific (Session). What isn't always clear is when the Cache object should be used rather than the Application or Session objects.
By default, the
Cache object has the same scope as the Application - data stored in it is globally accessible to all users. It's quite easy, and common, to use the Cache to store session data. This is typically done by joining the cache's key with an id that's associated with a particular user, for example:
What really makes the Cache object unique (since it clearly isn't its scope), is it's respect for system resources and flexibility. Specifically, both the
Session objects practically pin their data in memory. The Cache on the other hand uses a
WeakReference, which behaves quite differently. For the most part, storing data in the Cache doesn't guarantee that it'll be there - even for a second. If necessary, .NET will dump items from the cache to free up memory - and believe me, if .NET needs to start freeing up memory, you want to let it do whatever it has to. I've worked with developers who thought they could manage memory better than .NET, the result of this hubris has typically been
That's why whenever you retrieve a value from the Cache, you have to make sure it's not null. On the other hand, data stored in the
Session is going to be there when you pull it out. If you've used the Cache before, you are probably familiar with this type of defensive coding:
It might seem like a nuisance, but the benefits are worth it. In 95% of the cases, the Cache object is better to use than either the
Session objects. In some cases you'll have a relatively light chunk of data which is expensive to calculate/fetch/deduce. In this case, pinning data in memory might be an ideal solution. Even in those cases though, items inserted in the Cache can be marked with High or even
Aside from not being harmful to a system's stability, the Cache object is more flexible and powerful than either the Session or Application object. The ability to specify an absolute or sliding timeout, file or database dependency, callback method and a priority are all unique to the Cache object. The only thing the Cache object doesn't have is the ability to specify where the data is stored - it's always in-memory. As you probably know, it's possible to configure the Session to use either memory, state server or SQL Server - although this has to be configured for the entire application.
Finally, the last benefit the Cache object provides is that it can be safely used outside of a web context. If you have a class library, say for your business layer, you can reference
. Some developers have a hard time doing this within their Business layer, but it's completely safe. In all honesty, Microsoft should consider moving the Cache object outside of the
assembly to help developers get over the shock of seeing
references inside a library.
The reference returned by
is the same which is exposed by the Page property and
- so you can use them interchangeably. In fact,
(Caching data inside the business layer can make it more difficult to effectively unit test code. But there are ways to work around, and even, with it.)
The only problem with the Cache is that using it for session-based information can be a little messy. Always having to append a unique identifier to the key when inserting and retrieving data can be a pain. It would be nicer to encapsulate that within a class and have a clean API to work with. The
SessionCache class does exactly that. It's a very straightforward class which simply wraps the Cache object. Here's a partial implementation:
Inside a User Class
If you have a
User class within your project, you can even take it a step further and expose an instance of
SessionCache as one of its properties. Here's an example:
Consumers can then use a very clean API to store and retrieve user-specific information from the cache:
The Cache object has distinct advantages over both the Application and Session objects. It's more scalable and flexible without any real penalty. The
SessionCache is a simple layer of abstraction which wraps the Cache object into a lightweight shell, resulting in code that's easier to read, use and manage when dealing with session-based data.
Karl Seguin is an senior application developer at Fuel Industries, located in Ottawa, Ontario. He's an editor here at DotNetSlackers, a blogger for the influential CodeBetter.com and a Microsoft MVP.
This author has published 8 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.