ASP.NET Caching Gotcha
IT Chapters December 1st, 2006In an application I’ve been developing, we store the menu structure in an XML file. This was a .NET 1.1 application so it was before we had the chance of using the wonderful new controls in ASP.NET 2.0. I was developing today with my laptop was under some high load when the application stopped running and threw exceptions whenever the menu was being rendered. Can anyone spot the mistake in the code below?
if (Cache[”MenuDocumentXML”] == null)
{
//Create the dependency
System.Web.Caching.CacheDependency _MenufileDepend = new CacheDependency(Server.MapPath(”~” + “\\Menu.xml”));
//Get the file from the webroot and load it
System.Xml.XmlDocument MenuDocument = new XmlDocument();
MenuDocument.Load(Server.MapPath(”~” + “\\Menu.xml”));
//Insert the item into the cache
Context.Cache.Insert(”MenuDocumentXML”, MenuDocument, _MenufileDepend, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
}
return (XmlDocument) Cache[”MenuDocumentXML”];
The code here checks the cache for an item with the key MenuDocumentXML. No prizes for guessing what that contains. If it doesn’t exists, we create a filedependency on the actual xml file, load the xml file into an XMLDocument and then put this into the cache. The cache item expires after 30 minutes and will expire immediately if the file on disk changes.
The problem actually occurs in the last line. I’ve taken for granted that right after I added the item to cache it will be available. When the item doesn’t appear in the cache, we load it in, and outside the IF, we just pull the Menu directly from the cache.
However, my system was under load, and immediately after adding the item to cache, it was falling out, so the cache didn’t hold it anymore and therefore I was returning null every time.
The correct code should look like this:
System.Xml.XmlDocument MenuDocument;
if (Cache[”MenuDocumentXML”] == null)
{
//Create the dependencies
System.Web.Caching.CacheDependency _MenufileDepend = new CacheDependency(Server.MapPath(”~” + “\\Menu.xml”));
//Get the file from the webroot and load it
MenuDocument = new XmlDocument();
MenuDocument.Load(Server.MapPath(”~” + “\\Menu.xml”));
//Insert the item into the cache
Context.Cache.Insert(”MenuDocumentXML”, MenuDocument, _MenufileDepend, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
}
else
{
MenuDocument =(XmlDocument) Cache[”MenuDocumentXML”];
}
return MenuDocument;
In this example, when nothing is in the cache, we store the loaded XMLDocument into a variable immediately and then return that. In the case that the XMLDocument is in cache, we load it from the cache and then return it to the calling method.
Something small, but this is a gotcha that could potentially trip up your system.