0

I've researched, tapped friends and still can't get this to work. Even Caching in a console application really doesn't answer the question.

I have a scheduled task that runs this app once an hour for the next 12 hours that uses last years data as reference.

Of course, last years data is not going to change, a perfect case to use cache, especially since the query takes 90 to 110 seconds to run depending on how busy the server is.

using System.Runtime.Caching;

private static ObjectCache o_Cache = MemoryCache.Default;

private static IEnumerable<SWFSalesModel> GetLastYearsSalesData(ObjectCache o_Cache, string cacheKey) {
    IEnumerable<SWFSalesModel> arrLastYearsData = o_Cache.GetCacheItem(cacheKey) as IEnumerable<SWFSalesModel>;
    if (arrLastYearsData == null) {
        Console.WriteLine("Look in the cache 2");
        arrLastYearsData = (IEnumerable<SWFSalesModel>)o_Cache.Get(cacheKey);
    }
    if (arrLastYearsData == null) {
        Console.WriteLine("Look in the cache 3");
        arrLastYearsData = (IEnumerable<SWFSalesModel>)o_Cache[cacheKey];
    }
    if (arrLastYearsData != null) {
        return arrLastYearsData;
    } else {
        Console.WriteLine("nope, not in the cache");
        arrLastYearsData = GetLastYearSales(); ;
        CacheItemPolicy policy = new CacheItemPolicy();
        Console.WriteLine("Adding to the cache...");
        policy.AbsoluteExpiration = DateTimeOffset.Now.AddHours(12.0);
        o_Cache.Add(cacheKey, arrLastYearsData, policy);
        IEnumerable<SWFSalesModel> arrTest = (IEnumerable<SWFSalesModel>)o_Cache[cacheKey];
        if (arrTest != null) {
            /* This works 100% of the time */
            Console.WriteLine("it's in test cache!");
        } else {
            Console.WriteLine("nope, nada in test cache");
        }
        return arrLastYearsData;
    }
}

Then called in the program:

/* Get Last Years Sales Data */
string cacheKey = DateTime.Today.ToString("MM/dd/yyyy");
IEnumerable<SWFSalesModel> arrLastYearSales = GetLastYearsSalesData(o_Cache, cacheKey);

I've also tried it referencing the memory cache in the function as such:

private static IEnumerable<SWFSalesModel> GetLastYearsSalesData(string cacheKey) {
    ObjectCache o_Cache = MemoryCache.Default;
....
}

There is something that I obviously don't understand and would appreciate anyone's assistance on this immensely!

TaW
  • 53,122
  • 8
  • 69
  • 111
AZee
  • 205
  • 4
  • 9

1 Answers1

0

Ok, let's see some points:

  • Why are you casting from MemoryCache to ObjectCache? In this piece of code, I don't see any reason to do that;
  • Why are you testing 3 methods to get your cache? The GetCacheItem will return a CacheItem object, so your code will always fail there (at the as cast). Looking your piece of code, I think that just using the Get method is enough (it will return null in the case the cache doesn't exist);
  • Your time policy seens alright. If your schedule is exactly at the same policy expiration, you'll never refresh your cache.

So, I did a test with your code with 15s expiration policy, and just changing the time you can see that it works. Take a good look at your schedule time and compares it to your code, please.

private static MemoryCache o_Cache = MemoryCache.Default;

static void Main(string[] args)
{
    string cacheKey = DateTime.Today.ToString("MM/dd/yyyy");
    IEnumerable<SWFSalesModel> arrLastYearSales = GetLastYearsSalesData(o_Cache, cacheKey);

    Console.WriteLine();
    Console.WriteLine("Waiting 10 seconds...");
    Console.WriteLine();

    System.Threading.Thread.Sleep(10000);
    arrLastYearSales = GetLastYearsSalesData(o_Cache, cacheKey);

    Console.WriteLine();
    Console.WriteLine("Waiting 10 seconds...");
    Console.WriteLine();

    System.Threading.Thread.Sleep(10000);
    arrLastYearSales = GetLastYearsSalesData(o_Cache, cacheKey);

    Console.WriteLine();
    Console.WriteLine("Press a key...");
    Console.ReadKey();
}

private static IEnumerable<SWFSalesModel> GetLastYearsSalesData(MemoryCache o_Cache, string cacheKey)
{
    Console.WriteLine("Looking at the cache");
    var arrLastYearsData = (IEnumerable<SWFSalesModel>)o_Cache.Get(cacheKey);

    if (arrLastYearsData != null)
    {
        return arrLastYearsData;
    }
    else
    {
        Console.WriteLine("nope, not in the cache");
        arrLastYearsData = GetLastYearSales(); ;
        CacheItemPolicy policy = new CacheItemPolicy();
        Console.WriteLine("Adding to the cache...");
        policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(15);
        o_Cache.Add(cacheKey, arrLastYearsData, policy);

        IEnumerable<SWFSalesModel> arrTest = (IEnumerable<SWFSalesModel>)o_Cache[cacheKey];
        if (arrTest != null)
        {
            Console.WriteLine("it's in test cache!");
        }
        else
        {
            Console.WriteLine("nope, nada in test cache");
        }
        return arrLastYearsData;
    }
}

// just a test
private static IEnumerable<SWFSalesModel> GetLastYearSales()
{
    List<SWFSalesModel> result = new List<SWFSalesModel>();
    result.Add(new SWFSalesModel());
    result.Add(new SWFSalesModel());
    result.Add(new SWFSalesModel());

    return result;
}

This is the console result:

Looking at the cache

nope, not in the cache

Adding to the cache...

it's in test cache!

Waiting 10 seconds...

Looking at the cache

Waiting 10 seconds...

Looking at the cache

nope, not in the cache

Adding to the cache...

it's in test cache!

Press a key...

Anderson Rancan
  • 366
  • 5
  • 13
  • And it hit me like a ton of bricks. When the app starts as a scheduled task it will always having nothing in the cache. I need the app to run continuously for 12 hours in a loop. The first time it will have to fetch the data but the next 11 times the cache will be there. Back to the drawing board. Accepting your answer as it turned on the lights. Thank you. – AZee Aug 14 '15 at 22:08