Use Memcached in .NET application with Linq

First of all, get the memcached, I user win32 version. version 1.2.1
Secondly, get a client for memcached, I use this one 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="">
 <section name="memcached"
 type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
 <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 <> 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">
 <add name="MemcachedCacheProvider" type="MemcachedProviders.Cache.MemcachedCacheProvider, MemcachedProviders"
 keySuffix="_MySuffix_" defaultExpireTime="2000"/>

 <add address="" port="11211" />
 <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />

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

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.Add("keyString", l_serialized);
 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.



C# do not inherit parent class constructor

C# inheritance do not inherit parent class constructor.
If you want to invoke the parent constructor before doing anything in child constructor.
Define the child constructor as the following
ChildClassName(child parameter list) : base (child parameter list)
Two parameter lists do not need to be the same.

Example :

This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i) : base(i)

Parameter list in base do not need class specification.

Extension is static method, beware of its namespace

If you are using extension method within same namespace, carefully choose your method names.
Because extension methods is actually treat as static methods.
So, if you have extension method isEmpty() for let’s say Guid and TextBox.
And both of them are in namespace Your.Extension. The compile will complete without a problem.
But you will encounter error at runtime since both static methods have the same name.
You can either choose another name or separate them in different namespace.

Export using ReportViewer without viewing

ReportViewer is a great control. You can make drill down report and preview the report in the webpage.
Export as Excel or Pdf file easily, etc. Great features.

But, sometimes the user may not want to preview the report, the just want to get the file.
You can probably do that with Crystal report, but ReportViewer can just do the same, there is no point to shift.

Here is how to export as a byte stream. Use the LocalReport.Render()

Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
//export to excel, use "PDF" is you would like pdf format
byte[] l_reportBytes = rv_waterLicenseReport.LocalReport.Render("Excel", null, out mimeType, out encoding, out extension, out streamids, out warnings);
//setup the file name
Response.AddHeader("Content-Disposition", "attachment; filename=" + "ApplicationForm" + tb_LicenseNo.Text.Trim() + ".xls");
Response.AddHeader("Accept-Header", l_reportBytes.Length.ToString());
//define mime type
Response.ContentType = "application/";
Response.OutputStream.Write(l_reportBytes, 0, l_reportBytes.Length);

Strangely, the one page report of mine will export out as two page with the second page blank.
I will look into that later. For how to create a report, see my other post.

Data Struct in HashTable is ReadOnly

I once use a HashTable to work as a fast data lookup for some struct.
And I use a delegate to implement the Find() method to lookup.

Everything works fine until I try to modify values of the struct that my Find() gives me.
I later find out that because struct is a value type variable.
That means, my Find() return a copy of that struct, modifying it is just useless.

So, HashTable with struct AS-IS readonly.
If you want to have a HashTable with object that is changable,
simply use Class instead of struct.

Well, actually, struct is recommended to use for read only data in MS press book.