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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With