0

I'm having a strange problem with the Enterprise Library 5 Caching Block where two applications are sharing the same database cache. I've written a very simple static cache manager class which wraps up creating the EntLib5 ICacheManager, and reading/writing to it.

private static ICacheManager _manager = null;

private static ICacheManager Manager
{
    get
    {
        lock (ClientLock)
        {
            if (_manager == null)
                _manager = CacheFactory.GetCacheManager();

            return _manager;
        }
    }
}

public static object Get(string cacheKey)
{
    return Manager.GetData(cacheKey);
}

public static void Add(string cacheKey, object cacheItem)
{
    Manager.Add(cacheKey, cacheItem);
}

My database is setup correctly as are the configuration files and I can read & write to the database cache from a single console application with no problems.

However I'm trying to do a test between two applications sharing the same cache. The problem seems to be that if the Static CachingManager class in Console_A adds items to the Cache, after Console_B has instantiated it's static CacheManager, the changes are not picked up by Console_B.

Here's a quick timeline to explain.

Start Console_A

Write Item1 from Console_A to Cache - (Static ICacheManager created with noticeable 1sec pause) Success - 1 Item in Cache
Write Item2 from Console_A to Cache - Success - 2 Items in Cache
Write Item3 from Console_A to Cache - Success - 3 Items in Cache

Start Console_B

Read Item1 from Cache to Console_B - (Static ICacheManager created with noticeable 1sec pause) - Success - 3 Items in Cache
Read Item2 from Cache to Console_B - Success - 3 Items in Cache
Read Item3 from Cache to Console_B - Success - 3 Items in Cache

Write Item4 from Console_A to Cache - Success - 4 Items in Cache (Confirmed in DB)
Read Item4 from Cache to Console_B - Failure - 3 Items in Cache

So it seems that once Console_B initially sets up it's cache manager, it doesn't go back to the database to refresh the data. the Contains

I've tried removing the if(_manager == null) check from my Property as well so that it pulls a new CacheManager from the factory everytime but it made no difference.

Any advice appreciated.

EDIT

It would seem that the LoadItems Sproc only gets called when the ICacheManager is instantiated but never again during the application life cycle regardless of whether you call the CacheFActory / Unity EntLibContainer again.

Eoin Campbell
  • 43,500
  • 17
  • 101
  • 157

2 Answers2

1

The application domain of Console_A and Console_B are different. Even though you've defined your cache manager to be static it will not exist beyond the application domain therefore you have in reality two separate cache managers that do not know about each other.

I'd recommend using a service (WCF) and calling your business methods through that service, that way all console applications will be calling the same service and it will have one instance of a cache manager residing in it's own application domain.

rie819
  • 1,249
  • 12
  • 19
  • But I thought the point of moving the cache backing store to the DB would be to get around this exact issue. This would make the the EntLib Caching Block pretty useless out-of-the-box in a multi-server loadbalanced environment where you wanted to do caching between multiple nodes, because you'd still need to build a Single WCF Service to co-ordinate all cache calls. – Eoin Campbell Mar 22 '12 at 15:19
  • Caught with my pants down. I didn't read close enough to realize you'd moved the cache backing store to the DB. IMO I agree, it should work. Sorry I wasn't of any help. – rie819 Mar 22 '12 at 17:25
  • no problem. as it turns out it shouldn't. Apparently the EntLib Caching block was never design for not meant to be used as a Distributed Cache. It's purely an in-memory cache, and the DB Backing Store is only designed for retrieving CacheState in the event that the service falls over. Back to the drawing board to find an alternative option to EntLib#s Cache. :( – Eoin Campbell Mar 22 '12 at 17:27
  • Again without knowing your scope, If you have shared data that's going to be used in multiple applications, it sounds like a good candidate for SOA design. The shared data is in it's own service that can be called by either application. – rie819 Mar 22 '12 at 17:47
  • We already have a SOA Architecture in place. The problem is that using a single WCF service as the cache point limits it's scalability. You can't load balance/distribute that service. Don't worry about it. Already looking at memcache/ncache & AppFabric alternatives that are specifically designed for Distributed scenarios. EntLib was just an easy go-to as we already use it for Data/Logging & ExceptionHandling – Eoin Campbell Mar 22 '12 at 17:56
0

This is by design.

The enterprise library caching block is designed as an In Process Cache, and even when using a DB Based backing store, that's only for State Recovery in the event you're application is restarted. It was not designed to be used as a distributed cache.

Ref: Chris Tavares - MS Patterns & Practices Team

Community
  • 1
  • 1
Eoin Campbell
  • 43,500
  • 17
  • 101
  • 157
  • Also see http://msdn.microsoft.com/en-us/library/ff664556(v=pandp.50).aspx: "Other caching solutions would be more suitable in situations such as are when there are multiple applications using the cache or when the cache and the application are not on the same system. For example, you cannot synchronize caching across a Web farm." – Randy Levy Mar 23 '12 at 05:56