Sitecore has several layers of caching. However, it is sometimes necessary to add your own caching as well.
For the most part, this would only be necessary if you are either retrieving additional content from an external source or doing some processing of Sitecore content that you want to avoid repeating. This post will show a couple of options for implementing caching that is invalidated by a publishing operation.
The Sitecore API actually includes a decent starting point for your caching needs. The abstract class Sitecore.Caching.CustomCache provides most of the caching functionality that you will need. Max at Image0 blogged about this approach a couple of years ago. My version of this has mostly subtle differences, but there is one exception. I have added event handling to clear the cache after a publish job. I was surprised to find that this is not provided by the CustomCache class already, but it is simple enough to add. Since I can’t think of any reason why someone wouldn’t want this cache to be cleared on publish, I opted for registering the event handler in the constructor as opposed to the configuration file.
Note that when using the SetObject method that you have to provide an estimated size of the object you are adding to the cache. The Sitecore.Reflection.TypeUtil class can help you build your estimate. You will need to add up the estimated sizes of all data stored in the fields of your object. It is better to estimate high since on 32-bit machines, you can get out of memory exceptions by estimating too low. On a 64-bit machine with cache size limits disabled, this is just wasted effort.
The CustomCache class works well, but it requires a fair amount of code. Also estimating the size of the objects that you are putting into the cache is an unnecessary pain. It would be nice if we could use the normal ASP.NET cache but have it cleared after publishing. This is surprisingly easy to achieve by creating a class that inherits from System.Web.Caching.CacheDependency. The PublishCacheDependency class below simply registers itself for the publish:end and publish:end:remote events. The handler for these events just calls the NotifyDependencyChanged event that is inherited from the base class. It also overrides the DependencyDispose method so it can unsubscribe when the job is done.
Note that the name of event handler method includes the name of the class. This is to ensure that the method has a unique name. As I was writing this post, I discovered that the Event.Unsubscribe method contains a bug that causes any event handlers that share a name to be unsubscribed simultaneously. That is, if I have several classes that register an event handler with the name OnPublishEnd and then unsubscribe one of them, they will all be unsubscribed.
Rather than having a dedicated CacheManager class, I prefer to have a manager class for the content. This class generally knows how to get the content, process it, and cache it. The caching is encapsulated so that the consumer doesn’t need to know if or how it is implemented.
You can see that both options are very similar from the perspective of the consumer, but the CustomCache class requires quite a bit more code. The PublishCacheDependency class can even be added to your Sitecore library and reused all over the place.
Why then would you use the CustomCache approach? I can only think of one reason. When you instantiate a CustomCache class, it is registered with Sitecore’s CacheManager. This would allow you to have your cache cleared when the CacheManager.ClearAllCaches method is called. However, that method does not get called very often. It should almost never get called on a CD server.
If the content that you are caching is used only for a front-end website (as opposed to an application within the Sitecore client), I think the PublishCacheDependency is the way to go.