The CRM developer Sir Les told me how he used .NET 4 caching in some plugin code to cache some query data which was used by a plugin.
My first response was
What the heck is caching .NET4?
Quickly followed by
I want to have a look at the code and see how the magic works.
What is Object caching .NET 4?
Object caching is baked into the core .NET files and can be found in the namespace
The classes in this namespace provide a way to use caching facilities like those in ASP.NET, but without a dependency on the System.Web assembly.
From a CRM point of view caching was brought in with version .NET 4.0 so this means you can use caching with CRM 2011, CRM 2013 and CRM 2015.
I will add at this point I haven’t really used any other .NET caching but from the link above it seems you could do caching using the System.Web but I don’t really know much about it and it doesn’t seem like it’s a good time to learn about what was but instead we shall learn about what is in
System.Runtime.Caching and the Object caching it offers.
This type of caching is InMemory caching using the object
This offers a simple way to cache some object in the .NET memory, which sounds like a useful tool for plugins running on the CRM server when using static (ish) data.
The MemoryCache Constructor has some interesting points
When this constructor is invoked, configuration settings are first retrieved from application configuration files. If no configuration entries exist in the application configuration file, only the settings provided in config are applied
There is no mechanism to enforce unique names for cache instances. Therefore, it is possible to have multiple cache instances with the same name.
An important point is it won’t stop you adding duplicate keys so you must monitor and keep track of this yourself.
The last class you need to know about is
Reading articles about ObjectCache and looking at code examples it seems to be an easy to use and not very complex method to cache objects. This may mean you might run into problems with creating multiple objects cached with the same name, so I advise some caution.
Lets see the code
In this line, we are obtaining a reference to the default MemoryCache instance. Using the new .NET Caching runtime, you can have multiple MemoryCaches inside a single application.
You need to add this using
using System .Runtime .Caching ;
This line gets a reference to the default MemoryCache instance
ObjectCache Cache = MemoryCache .Default ;
To add something to the cache
const string key = “IncidentMetaData”;
List<string > testData = new List<string> { “Meta1”, “Meta2”, “Meta3” };
Cache.Add (key, objectToCache, DateTime.Now.AddHours(24));
The code has added the List<string> test data into the memory cache with the name “IncidentMetaData”. From a CRM perspective this is a similar to items in the Attributes collection on an entity.
You can get things out from the cache by doing this
cache.Get(keyText)
The keyText is the name of the cacheObject you want to retrieve, if you wanted to get the example above you would type in “IncidentMetadata”.
There is other functionality which can monitor changes for cached files.
There is other functionality to remove items from the cache.
Cache.Remove(key);
Code to get started
I have only briefly only mentioned the functionality, I would advise you to read this blog and download the sample code and you can use the static class. This first blog I found the most useful
These other blogs will give you some more reading and examples
System.Runtime.Caching Namespace
How to: Cache Objects Simply using System.Runtime.Caching.MemoryCach
Working with System.Runtime.Caching.MemoryCache
When to use the in memory cache with CRM
Most of the time I don’t think you would need to use this code in CRM plugins because it’s easy to store and retrieve data from CRM using LINQ or QueryExpression queries.
The in memory cache is suitable for queries which return the same data most of the time.
This could be things like
- Language settings
- Config file settings
- Metadata
In the example I am using I am retrieving all the metadata for the incident entity and this data would be retrieve many times in short period of time whilst 100 of records would be imported. In this scenario it made sense to cache the data.
Consider this would create a cache on each CRM server because the cache works on server basis.
plugins triggered by importing
if you have plugins which are triggered when importing lots of records, you may benefit from caching some queries.
I thought I would blog about this because it seemed like an interesting tool developers might want to use. Be aware there could be limitations and gotcha’s I haven’t worked out yet
I certainly wouldn’t overuse this because most queries retrieving records in CRM run quickly, with the majority of plugins performance is not an issue
One of those ‘gotchas’ is that this does not fully work for sandboxed plugins due to the isolated nature of the executing plugin host.
LikeLike
Hi Scott
I hadn’t considered the effects of sandboxed plugins. I tested this on our dev environment where the plugins are of isolation type = sandboxed.
The caching worked without problems.
I guess this wouldn’t work on CRM online instances but this worked for plugins on premise
I haven’t monitored this much yet, so things gotcha’s could still be lurking
LikeLike
You might see the cache working but it’ll be short lived because the process that the sandbox plugin runs within is frequently torn-down/restarted.
LikeLike
Interesting, this has got me thinking. I thought this object caching worked on a .NET level but if doesn’t then my cached query values will soon be washed away as sandbox processes pop up and down rather quickly.
Thanks for the reply, more investigation needed by myself
LikeLike
As Scott mentioned, System.Runtime.Cache doesnt work consistently with 365 online, so is there any preferred caching method in 365 online? I am using paging and currently have to re-fetch 1000’s of records from external http connection for each page!
LikeLike