Cache usage in Winform

Cache is needed in many cases, Rational use of cache can On the one hand, it can improve the response speed of the program, while reducing the pressure of accessing specific resources. This article mainly introduces the use of cache in Winform. I hope you can learn some cache usage scenarios and methods. Caching is a problem that must be considered for a medium and large system. In order to avoid accessing background resources (such as databases) every time a request is made, we usually consider temporarily saving some data that is not updated very frequently and can be reused in a certain way, and subsequent requests can directly access these saved data according to the situation. This mechanism is called caching mechanism.

The caching function of. NET 4.0 mainly consists of three parts: System Runtime.Caching, System.Web.Caching.Cache and Output Cache.

System.Runtime.Caching NET 4.0 mainly uses the MemoryCache object, which exists in the assembly System Runtime.Caching.dll。

System.Web.Caching.Cache The cache objects that have existed since the beginning of NET2.0 are generally used in the Web, and can also be used in Winform. However, you should refer to System Web.dll。

Output Cache is Asp NET, in ASP NET versions before 4.0 use System directly Web.Caching.Cache to cache HTML fragments. In ASP NET 4.0 provides an OutputCacheProvider for developers to extend, but it still uses System by default Web. Caching. Cache.

1. Customize the cache processing of Hastable.

In addition to the above three caching mechanisms, we can also store and use customized caches in static objects through HashTable or Dictionary.

For example, in my own developed programs, I use factory classes to create business objects. Because creating business objects and data access layer objects is an operation that is repeatedly called on the interface or the middle layer, it is necessary to store the frequently called objects and directly fetch them from memory when downloading and calling. For example, the BLLFactory class below is a business class creation operation based on generic objects, which uses Hashtable based static objects for caching.

     ///  <summary>
     /// The factory class that constructs the business class ///  </summary>
     ///  <typeparam name="T"> Business Object Type </typeparam>
     public  class BLLFactory<T> where T : class { private  static Hashtable objCache = new Hashtable(); private  static  object syncRoot = new Object(); ///  <summary>
         /// Create or obtain the instance of the corresponding business class from the cache ///  </summary>
         public  static T Instance { get { string CacheKey = typeof (T). FullName; T bll = (T)objCache[CacheKey];   // Read from cache
                 if (bll == null ) { lock (syncRoot) { if (bll == null ) { bll = Reflect<T>. Create( typeof (T). FullName, typeof (T). Assembly.GetName(). Name); // Reflection creation and caching
                             objCache.Add(typeof (T). FullName, bll); } } } return bll; } } }

2. Use NET 4.0's MemoryCache object implements caching

The use of MemoryCache is rarely introduced online, but this is NET 4.0 newly introduced cache object is estimated to replace the cache module of the original enterprise library NET cache can be everywhere, rather than based on a specific version of Windows.

First, we use to create an auxiliary class MemoryCacheHelper based on MemoryCache, which is convenient for calling for cache processing.

     ///  <summary>
     /// Cache auxiliary class based on MemoryCache ///  </summary>
     public  static  class MemoryCacheHelper { private  static  readonly Object _locker = new  object (); public  static T GetCacheItem<T>(String key,  Func<T> cachePopulate, TimeSpan? slidingExpiration = null ,  DateTime? absoluteExpiration = null ) { if (String.IsNullOrWhiteSpace(key)) throw  new ArgumentException( " Invalid cache key " ); if (cachePopulate == null ) throw  new ArgumentNullException( " cachePopulate " ); if (slidingExpiration == null && absoluteExpiration == null ) throw  new ArgumentException( " Either a sliding expiration or absolute must be provided " ); if (MemoryCache.Default[key] == null ) { lock (_locker) { if (MemoryCache.Default[key] == null ) { var item = new CacheItem(key, cachePopulate()); var policy = CreatePolicy(slidingExpiration,  absoluteExpiration); MemoryCache.Default.Add(item, policy); } } } return (T)MemoryCache. Default[key]; } private  static CacheItemPolicy CreatePolicy(TimeSpan?  slidingExpiration, DateTime? absoluteExpiration) { var policy = new CacheItemPolicy(); if (absoluteExpiration.HasValue) { policy.AbsoluteExpiration = absoluteExpiration.Value; } else  if (slidingExpiration.HasValue) { policy.SlidingExpiration = slidingExpiration.Value; } policy.Priority = CacheItemPriority.Default; return policy; } }

This auxiliary class has only one public method, GetCacheItem. When using it, you need to specify the key, the processing agent for obtaining data, and the cache expiration time, whether it is based on TimeSpan or absolute time.

When can we use the above auxiliary classes?

If a person ID is used in a workflow module, and the person ID needs to be escaped, and the person information is generally stored in the permission system module, then if the person ID needs to be escaped frequently in the workflow, then you need to call the interface module of the permission system, In this way, the cache module can be used for optimization processing.

         void gridView1_CustomColumnDisplayText( object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) { if (e.Column.FieldName.Equals( " ProcUser " ) || e.Column. FieldName.Equals( " ProcUid " ) || e.Column. FieldName.Equals( " UserId " )) { if (e.Value != null ) { e.DisplayText = SecurityHelper.GetUserFullName (e.Value.ToString()); } } }

The SecurityHelper GetUserFullName is my cache based secondary encapsulation of calls. The specific logic is shown below.

         ///  <summary>
         /// Get the user's full name according to the user's ID and put it in the cache ///  </summary>
         ///  <param name="userId"> User's ID </param>
         ///  <returns></returns>
         public  static  string GetUserFullName( string userId) { string key = " Security_UserFullName " + userId; string fullName = MemoryCacheHelper.GetCacheItem< string > (key, delegate () { return BLLFactory<User> .Instance.GetFullNameByID(userId.ToInt32()); }, new TimeSpan( zero , thirty , zero )); // 30 minute expiration
             return fullName; }

Func<T>in the method GetCacheItem of MemoryCacheHelper uses an anonymous function to obtain the cached value.

 delegate () { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }

Call BLLFactory<User> Instance.GetFullNameByID gets the corresponding data from the database.

In this way, the method of the business object class is automatically called to obtain data the first time or when the cache expires.

Finally, call the GetUserFullName method on the interface to realize the call based on the cache method. If the program is used for the first time and there is no data when it encounters the specified key, it will go to the database to obtain the data. If it encounters the key later, it will directly obtain the cached data.

The following figure is the specific implementation effect of the program.

Of course, the above two methods can also achieve code simplification through AOP injection. However, because the introduction of AOP will involve more knowledge points, and the familiarity with the program is not enough, we still use more common methods to process cached data.

 

posted on 2014-01-20 00:00   Wu Huacong   Reading( thirty-five thousand nine hundred and nine Comments( thirteen edit   Collection   report

Navigation