. NET Cache Module Design

Source: Internet
Author: User

The previous article talked about my concept of caching, the framework of understanding and views, this article to take up my own cache module design practice.

Basic Cache Module Design

The most basic cache module must have a unified cachehelper, as follows:

     Public Interface Icachehelper    {              T Get<T> (string  key);                        void Set<t> (string  key, T value);                void Remove (string  key);                   

Then the business layer is called in this way

         PublicUser Get (intID) {if(ID <=0)                Throw NewArgumentNullException ("ID"); varKey =string.            Format (User_cache_key, id); varuser = _cachehelper.get<user>(key); if(User! =NULL)                returnuser; return_repository.        Get (ID); }    

There is nothing wrong with the code above, but the actual use of it is problematic, because I have always stressed that the cache to save "hot data", so that "hot data" must have expired, we can not write another to set. So it is more appropriate to combine the writing together.

 PublicUser GetV2 (intID) {    if(ID <=0)       Throw NewArgumentNullException ("ID"); varKey =string.    Format (User_cache_key, id); varuser = _cachehelper.get<user>(key); if(User! =NULL)       returnuser;
User=_repository. Get (ID); if(User! =NULL) _cachehelper.set (key, user);
returnuser;}

The above code is just adding a set, so the design, each time a get need to repeat the code is too much, then should be more streamlined? This time to eat some C # syntax sugar is necessary, grammar sugar occasionally eat a little to improve efficiency, why not?

 PublicUser GetV3 (intID) {      if(ID <=0)          Throw NewArgumentNullException ("ID"); varKey =string.       Format (User_cache_key, id); return_cachehelperv2.get<user> (key, () =_repository.            Get (ID)); }//ICache get<t> Implementation PublicT get<t> (stringKey, func<t> fetch =NULL) {T result=default(T); varobj =Cache.get (key); if(obj isT) {result=(T) obj; }    if(Result = =NULL) {result=fetch (); if(Result! =NULL) Set (key, result); }    returnresult;} 

Here I have directly packed the set method into the Icache.get<t>, with fetch Func attached. This abstracted the public operations together, simplifying the call of the cache, which perfectly fits my mind.

Advanced Cache Module Design

The Icache V3 in the previous section was almost the most streamlined, but in fact, after referring to Servicestack.redis, I discovered a more abstract approach. Obviously all the code in the previous section is manually managed key, and for the usual object cache, does this key need to be manually? to the last improvement.

 PublicT get<t> (ObjectID, func<t> fetch =NULL){    varType =typeof(T); varKey =string. Format ("urn:{1}:{2}", type. Name, ID. ToString ());//Here is the key, directly using TypeName to act as keyreturnGet (key, Fetch);} PublicT get<t> (stringKey, func<t> fetch =NULL) {T result=default(T); varobj =Cache.get (key); if(obj isT) {result=(T) obj; }    if(Result = =NULL) {result=fetch (); if(Result! =NULL) Set (key, result); }     returnresult;}

The Get method completely automates the management of key and then calls the way it is streamlined again.

 Public User GetV4 (int  ID) {     if0)        throwNew ArgumentNullException ("ID");      return _cachehelperv3.get<user> (ID, () = _repository. Get (ID));}

It's obvious that the most important set, the set, this key acquisition is going to cost a little bit, the most need to solve is how to get the value of the primary key ID.

 Public classuser{[PrimaryKey]//This attribute is the most important thing.         Public intUserId {Get;Set;}  Public stringUserName {Get;Set; }  Public stringCellphone {Get;Set; }} Public voidSet<t>(T obj) {//This should be cached here to improve the efficiency of reflection      varType =typeof(T); varPrimaryKey =type. GetProperties (). FirstOrDefault (t= T.getcustomattributes (false)                    . Any (c= C isprimarykeyattribute)); /here to get the value of ID by taking PrimarykeyattributevarKeyValue = Primarykey.getvalue (obj,NULL); varKey =string. Format ("Urn:{0}:{1}", type.       Name, KeyValue); varDT = DateTime.UtcNow.AddDays (1);//Suppose the default cache is 1 days        varoffset =NewDateTimeOffset (DT); Cache.set (key, obj, offset);}

Here I think the final version of Icache is complete. It also needs to be explained that the PrimaryKey can be more flexible and changeable. Many times a primarykey of an object is very complex, and this time the cache entity can be designed with the following modifications:

 Public classusercacheentity{[PrimaryKey] Public intID {Get            {                return string. Format ("{0}:{1}", UserId, UserName); }        }         Public intUserId {Get;Set; }  Public stringUserName {Get;Set; }  Public stringCellphone {Get;Set; }}

The above method can almost automatically manage the common data cache, the only trouble is the need to customize a cacheobject, which brings the problem of entity conversion, it is necessary to see how to choose.

Again, I want the Icache design:

1. Always cache hot data, which means that each key has an expiration time

2. Icache Automatic management of Get/set, it is best to automatically manage key.

3. Icache streamlining without losing flexibility.

The detailed code demo can refer to: Git

More flexible implementations

Before I write this summary, I have been thinking about what layer the cache should be placed on and where to put it on the three floor. Where do you put your ddd when it's layered? Google, see a few references.

Http://stackoverflow.com/questions/15340173/in-which-layer-implement-the-cache

I think this is more in line with my idea, the cache should be global arbitrary, of course, the implementation of course is INTERFACE+IOC, so the reference is more independent.

In addition to the more advanced use of the cache, AOP combined with Icache V4 such a design, wouldn't it be better? Here I have not to realize the attribute of AOP, this is another big topic, next time come to realize it.

This article is more humble, welcome everyone to shoot bricks, look forward to common progress.

. NET Cache Module Design

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.