views:

408

answers:

1

Hi all,

I'm working on an asp.net MVC application.

I have a class that wraps a repository that fetches data from a db using simple linq statement. I've written a decorator class to add caching logic (using caching application block).

since I have several methods that I want to decorate, and the logic is all the same for each one (check if exists in cache, if not invoke real getter and store in cache), I wrote something like this:

a helper method that does the common logic of checking if exists in cache and so on:

 public object CachedMethodCall(MethodInfo realMethod, params object[] realMethodParams)
 {
  object result = null;
  string cacheKey = CachingHelper.GenereateCacheKey(realMethod, realMethodParams);

  // check if cache contains key, if yes take data from cache, else invoke real service and cache it for future use.
  if (_CacheManager.Contains(cacheKey))
  {
   result = _CacheManager.GetData(cacheKey);
  }
  else
  {
   result = realMethod.Invoke(_RealService, realMethodParams);

   // TODO: currently cache expiration is set to 5 minutes. should be set according to the real data expiration setting.
   AbsoluteTime expirationTime = new AbsoluteTime(DateTime.Now.AddMinutes(5));
   _CacheManager.Add(cacheKey, result, CacheItemPriority.Normal, null, expirationTime);
  }

  return result;
 }

this all works fine and lovely. in each decorated method I have the following code:

StackTrace currentStack = new StackTrace();
string currentMethodName = currentStack.GetFrame(0).GetMethod().Name;
var result = (GeoArea)CachedMethodCall(_RealService.GetType().GetMethod(currentMethodName), someInputParam);
return result;

the problem is that sometimes the line where realMethod.Invoke(...) is happening returns null. If I put a breakpoint right after and then return the execution to that line, result is not null and data is fetched from the DB. all the input variables are correct, data exists in the DB, 2nd run gets the data, so what goes wrong in the first run?!

thanks :)

A: 

I think I managed to solve this problem by updating the code as follows:

 public object CachedMethodCall(MethodInfo realMethod, params object[] realMethodParams)
 {
  string cacheKey = CachingHelper.GenereateCacheKey(realMethod, realMethodParams);

  object result = _CacheManager.GetData(cacheKey);

  if (result == null)
  {
   result = realMethod.Invoke(_RealService, BindingFlags.InvokeMethod, null, realMethodParams, CultureInfo.InvariantCulture);

   // TODO: currently cache expiration is set to 5 minutes. should be set according to the real data expiration setting.
   AbsoluteTime expirationTime = new AbsoluteTime(DateTime.Now.AddMinutes(5));
   _CacheManager.Add(cacheKey, result, CacheItemPriority.Normal, null, expirationTime);
  }

  return result;
 }

I noticed that the previous _CacheManager.Contains call was sometimes returning true even though the cache did not contain the data. I suspect threads causing the problems, but I'm not sure...

Ami