Prism enterprise Cache Manager

Caching is a advanced topic if you decied to develope some enterprise level application. There are a case studied in this page "Cache and DataBase synchronization through SqlDependency". 

 

 

A feel of the CacheManager

 

However, in this article, I am going to show a flavor of the CacheManager by analysing a consistence issue regarding CacheManager. The code and the configuration is based on "Microsoft Enterprise Library Caching Application Block not thread safe?"

 

 

First let see the configuration in a file called EnterpriseCacheManager.config file.

 

 

 

<configuration>
  <configSections>
    <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <cachingConfiguration defaultCacheManager="Cache Manager">
    <cacheManagers>
      <add expirationPollFrequencyInSeconds="1" maximumElementsInCacheBeforeScavenging="1000"
      numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"
      type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
      name="Cache Manager" />
    </cacheManagers>
    <backingStores>
      <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
      name="Null Storage" />
    </backingStores>
  </cachingConfiguration>
</configuration>

 

 

 

and the source code that manipulate the CacheManager is like this : 

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;

namespace EnterpriseCacheManager
{
  class Program
  {
    public static ICacheManager cacheManager = null;

    private static void InitializeCacheManager()
    {
      if (cacheManager == null)
      {
        var fileSource = new FileConfigurationSource("EnterpriseCacheManager.config");
        var factory = new CacheManagerFactory(fileSource);
        cacheManager = factory.CreateDefault();
      }
    }
    
    static void Main(string[] args)
    {
      Test2();
    }

    private static void Test1()
    {
      InitializeCacheManager();

      while (true)
      {
        System.Threading.Thread.Sleep(1000);
        var key = new Random().Next(3).ToString();
        string value = "";

        lock (cacheManager)
        {
          if (!cacheManager.Contains(key))
          {
            cacheManager.Add(key, key, CacheItemPriority.Normal, null, new SlidingTime(TimeSpan.FromSeconds(5)));
            value = (string)cacheManager.GetData(key);
          }
        }

        Console.WriteLine("{0} ---> '{1}'", key, value);
      }
    }


    static void Test2()
    {
      /**
       *
       * As explained in the reply from Tuzo, in his own word. &lt;quote&gt;http://stackoverflow.com/questions/1302643/microsoft-enterprise-library-caching-application-block-not-thread-safe/&lt;quote&gt;
       * What you are seeing is that your CacheItem has expired due to the 5 second SlidingTime expiration.

Before returning the cached value, the GetData method performs a check to see if the CacheItem has expired. If it has expired, the CacheItem is removed from the cache and null is returned. However, the call to Contains will return true because the CacheItem is in the cache even though it's expiration may have elapsed. This seems to be by design. With that in mind, it would be wise not to cache a null value to represent no data since you would not be able to discern an expired CacheItem from an actual cached value of null.

Assuming that you do not cache a null value then Luke's solution should suit you:
       */
      InitializeCacheManager();

      while (true)
      {
        System.Threading.Thread.Sleep(1000);
        var key = new Random().Next(3).ToString();

        string value = "";

        lock (cacheManager)
        {
          value = cacheManager.GetData(key) as string;
          if (value == null)
          {
            value = key;
            cacheManager.Add(key, value, CacheItemPriority.Normal, null, new SlidingTime(TimeSpan.FromSeconds(5)));
          }
          value = cacheManager.GetData(key) as string;
        }

        Console.WriteLine("{0} ---> '{1}'", key, value);
      }
    }
  }
}
 

 

If you run Test1(), then you might see something like this in the output.

 

 

2 --> '2' 1 --> '1' 2 --> '2' 0 --> '0' 2 --> '2' 0 --> '0' 1 --> '' 0 --> '0' 1 --> '1' 2 --> '' 0 --> '0' 2 --> '2' 0 --> '0' 1 --> '' 2 --> '2' 1 --> '1' Press any key to continue . . .

 

 

What CacheManager can lend itself to?

 

CacheManager can have the following. 

 

GetDate

StoreData

Flush

Remove

Expiration time on CacheItem

Expiration Strategy on cacheItem (FileDependency (when file is updated), AbsoluteTime, NeverExpired, SlidingTime (time window))

...

 

 

 

NOTE: This topic may deserve further exploration.

 

 

 

 

 

你可能感兴趣的:(.net)