Use Memcached in .NET application with Linq

First of all, get the memcached, I user win32 version. http://jehiah.cz/projects/memcached-win32/ version 1.2.1
Secondly, get a client for memcached, I use this one http://memcachedproviders.codeplex.com/ version 1.2
Get the document for the client too, I start without it and I think you should read it in advance.
I will share some of my experience too.

The official documentation is a bit poor, I am going to give an introduction on the main points.

1. Memcached is a universal distributed cache.

i.e. it can run multiple instances and appears to the programmer as one cache server which is programming language independent. A really large hashtable.

2. It stores no object, you’ll have to serialze every object that you want to cache.

3. It won’t throw any exception no matter what happens.

I will focus on how to use the memcached server, not how to setup since you should be run it without a problem.

Setup the client in your application. Unarchive and add reference to all three .dll in your project.

Then configure your web.config or app.config like this, inside <configSections> tag, add the following:

<section name="cacheProvider" type="MemcachedProviders.Cache.CacheProviderSection, MemcachedProviders"
 allowDefinition="MachineToApplication" restartOnExternalChanges="true"/>
 <sectionGroup name="enyim.com">
 <section name="memcached"
 type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
 </sectionGroup>
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>

This tells the application that there will be a section with tag <cacheprovider> and <log4net>. Also will have a section with tag <enyim.com> who has a child tag <memcached> inside. You can just copy and paste the above, it should work.

Then add the detail settings in <configuration> tag.

<cacheProvider defaultProvider="MemcachedCacheProvider">
 <providers>
 <add name="MemcachedCacheProvider" type="MemcachedProviders.Cache.MemcachedCacheProvider, MemcachedProviders"
 keySuffix="_MySuffix_" defaultExpireTime="2000"/>
 </providers>
 </cacheProvider>

 <enyim.com>
 <memcached>
 <servers>
 <add address="192.168.1.2" port="11211" />
 </servers>
 <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
 </memcached>
 </enyim.com>

 <log4net>
 <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
 <layout type="log4net.Layout.PatternLayout">
 <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}]- %message%newline" />
 </layout>
 </appender>
 <root>
 <priority value="WARN"/>
 <appender-ref ref="ConsoleAppender">
 <filter type="log4net.Filter.LevelRangeFilter">
 <levelMin value="WARN"/>
 <levelMax value="FATAL"/>
 </filter>
 </appender-ref>
 </root>
 </log4net>

You can change the default expire time. Server address is the host which you run memcached and 11211 is the default port.

Caching string and serialized object should be something you already know. For simple class, just add [Serializable] to the class.

Let’s see how it works with LINQ.

To serialize LINQ object, open .dbml design view, select serialize mode to unidirectional.

Then you will need to use DataContractSerializer to actually serialize your object. For more information.

There are a few serializer, XML, binary, JSON, etc. I am using DataContractJsonSerializer since it should be faster than XML. The following code snippet serialize and cache the object array to memcached.

//create a serialize provider with specify object type
DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
//a memory stream as buffer since the provider do not directly generate string
 using (MemoryStream ms = new MemoryStream())
 {
 serializeProvider.WriteObject(ms, myClassArrayObject);
 byte[] l_buffer = new byte[ms.Length];
 ms.Position = 0;
//If the string is out of integer range, skip it, you can do whatever you need to handle this
 if (ms.Length < int.MaxValue)
 {
 ms.Read(l_buffer, 0, (int)ms.Length);
 string l_serialized = Encoding.Unicode.GetString(l_buffer);
//remove existing cache with the same key
 DistCache.Remove("keyString");
 DistCache.Add("keyString", l_serialized);
 }
 else
 {
 throw new Exception("object data large.");
 }
 }

Then you can check whether you succussfully cache it with telnet.

Telnet to your server and type the command ‘stats’, it will then shows the status of your memcached.

curr_items is the number of items inside memcached.

There is some common practices in choosing the hash key but that is another topic.

I am using Application:Method:Parameters:Salt and then hash it with SHA256, convert it to base64.

This should be enough for testing purpose, you can come up with your own hash decision.

Then we will get the cache and deserialize it to our object.

string l_serialized = (string)DistCache.Get("keyString");
 DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
 using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(l_serialized)))
 {
 myClass[] members = (myClass[])serializeProvider.ReadObject(ms);
 }

You can do this with your object, object array, object collection, etc.

But remember you are in a different data context if you get you data from cache.

This will need some workaround to update or delete data with Linq.

I will cover this part later in another article.

中文版

One thought on “Use Memcached in .NET application with Linq

  1. Pingback: Memcached and Asp.net mvc « DucDigital

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s