views:

930

answers:

4

Am using following .net code to add objects to cache:

public static void Add<T>(string key, T dataToCache)
        {
            try
            {
                ApplicationLog.Instance.WriteInfoFormat("Inserting item with key {0} into Cache...", key);

                HttpRuntime.Cache.Insert(
                    key,
                    dataToCache,
                    null,
                    DateTime.Now.AddDays(7),
                    System.Web.Caching.Cache.NoSlidingExpiration);
            }

            catch (Exception ex)
            {
                ApplicationLog.Instance.WriteException(ex);             
            }
        }

and here is my code to retrieve values from cache:

public static T Get<T>(string key) 
        {   
            try
            {                
                if (Exists(key))
                {
                    ApplicationLog.Instance.WriteInfoFormat("Retrieving item with key {0} from Cache...", key);

                    return (T)HttpRuntime.Cache[key];
                }
                else
                {
                    ApplicationLog.Instance.WriteInfoFormat("Item with key {0} does not exist in Cache.", key);
                    return default(T); 
                }
            }
            catch(Exception ex)
            {
                ApplicationLog.Instance.WriteException(ex);
                return default(T); 
            }
        }



public static bool Exists(string key)
       {
           bool retVal = false;
           try
           {
               retVal= HttpRuntime.Cache[key] != null;
           }
           catch (Exception ex)
           {
               ApplicationLog.Instance.WriteException(ex);
           }
           return retVal; 
       }

But i find that after every 2 minutes or so,the cached object value is getting set to null resulting in pulling that value from database again.

What am i missing here?

+1  A: 

It could be because memory is running low, the cache will automatically kill off items in the cache when memory is becoming scarce, There is an optional parameter to set the priority of items in the cache if you want one item to be cleared before another.

Tetraneutron
+2  A: 

When you say every two minutes the value inserted is set to null, does that mean just the item you're interested in or every single item in the cache?

I ask this because the cache only exists as long as the application is running. If the application is restarted, the cache goes away. This would explain the behavior if everything goes away every 2 minutes. In that case you have a different problem on your hands: why does the application restart every 2 minutes.

If it's only SOME items then it could be a memory issue. The cache cleans itself up in response to low memory. I believe there's a way to set priority on values inserted. But this should only be a problem when you're low on memory.

If this still doesn't solve your problem, there is a way to discover why an item is being removed. It is explained here.

colithium
thanks for ur input...yes, the value is set to null for every item in the cache..
Can you check the logs to confirm if the app is restarting and if so why? Once you find that out you should be able to solve it or post another question.
colithium
+2  A: 

Well first of all your access isn't synchronized so that's a great source of problems. Reading from the HttpRuntime Cache is guarantied to be thread safe so you should really try reading your item as your first step on each and every cache operation.

Between checking if Exists and actually retrieving the item lots of things can happen (such as your item not beeing there anymore). You should get a handle of the item you're looking for, and if it isn't there provide thread-safe insert by fetching it from your persistent data store.

So your Add logic would get inside your Get IF the data isn't there. There's nothing fundamentally wrong in providing separate Add logic and you should measure the cost of hitting the database multiple times compared to blocking further requests for that specific piece of data.

T GetT(string key)
{
    T item = (cache.Get(key) as T);
    if (item == null)
    {
        lock (yourSyncRoot)
        {
            // double check it here
            item = (cache.Get(key) as T);
            if (item != null)
                return item;

            item = GetMyItemFromMyPersistentStore(key); // db?
            if (item == null)
                return null;

            string[] dependencyKeys = {your, dependency, keys};

            cache.Insert(key, item, new CacheDependency(null, dependencyKeys), 
                         absoluteExpiration, slidingExpiration, priority, null);
        }
    }
    return item;
}

Depending on your expiration policy you'll get your data in memory and provide fast & synchronized access to it, but as I said, measure it and adjust it to your needs. In your business logic after updating your item and properly saving it to your persistent store, just remove it from cache and the next call to your Get will fetch it again.

A: 

If you are using .NET 4. I wrote an article along with a helper class that makes using Caching easier. The article is about the new System.Runtime.Caching namespace that is available in .NET 4.

http://deanhume.com/Home/BlogPost/object-caching----net-4/37

Deano