Search This Blog

Thursday, September 3, 2009

Bind DropDownList Using Cache Value

Here I have created an AppCacheManager Class where i define some methods for Insert to Cache,Remove From Cache,Refresh Cache etc..
We need to use a synchronization primitive lock which is provided by the .NET Framework. Basically this mechanism allows a thread to acquire a lock on an instance of an object. Which means, only one thread can acquire a lock on the object and other threads have to wait until the original thread releases the lock .But if we lock the cache object directly it will be a huge performance issue.Acctullay we have to make sure that a)multiple threads can read cache data simultaneously, b)only one thread is allowed to update the cache at a time c) When a thread is updating the cache, all the threads that want to read the cache data should wait until the update is complete
The .NET framework provides another thread synchronization primitive called ReaderWriterLock
My Cache Manager Class is like that
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Data;
using System.Web.Caching;
using System.Threading;
using System.Reflection;
using AppConfigurationManagement
namespace CacheManagement
{
// contains the methods for cache management for Add ,Remove,Refresh
public static class AppCacheManager
{
private static System.Web.Caching.Cache _CacheManager = System.Web.HttpContext.Current.Cache;
private static ReaderWriterLock _ReadWriteLock;
static AppCacheManager ()
{
_ReadWriteLock = new ReaderWriterLock();
if (System.Web.HttpContext.Current != null)
{
_CacheManager = System.Web.HttpContext.Current.Cache;
}
else
{
_CacheManager = System.Web.HttpRuntime.Cache;
}
}
// Method to add object in cache
public static void AddToCache(EnumeratorsConfiguration.CacheKey key, object keyData)
{
try
{
// Aquire Writer Lock
_ReadWriteLock.AcquireWriterLock(60000);
_CacheManager.Insert(key.ToString(), keyData);
}
finally
{
if (_ReadWriteLock.IsWriterLockHeld)
{
_ReadWriteLock.ReleaseWriterLock();
}
}
}
/// Method to remove object from cache,
/// it removes object for all keys which starts with value of key
public static void RemoveFromCache(EnumeratorsConfiguration.CacheKey key)
{
try
{
_ReadWriteLock.AcquireWriterLock(60000);
System.Collections.IDictionaryEnumerator dicEnum;
dicEnum = _CacheManager.GetEnumerator();
while(dicEnum.MoveNext() == true)
{
if (((string)dicEnum.Key).StartsWith(key.ToString()))
{
_CacheManager.Remove((string)dicEnum.Key);
}
}
}
finally
{
//Release the write lock
if (_ReadWriteLock.IsWriterLockHeld)
{
_ReadWriteLock.ReleaseWriterLock();
}
}
}
/// Method to remove object from cache,
/// it removes object for all keys which starts with value of key
public static void RemoveFromCache()
{
try
{
_ReadWriteLock.AcquireWriterLock(60000);
System.Collections.IDictionaryEnumerator dicEnum;
dicEnum = _CacheManager.GetEnumerator();
while (dicEnum.MoveNext() == true)
{
if (IsCacheable(dicEnum.Key.ToString()))
_CacheManager.Remove((string)dicEnum.Key);
}
}
finally
{
//Release the write lock
if (_ReadWriteLock.IsWriterLockHeld)
{
_ReadWriteLock.ReleaseWriterLock();
}
}
}
public static DataTable GetCacheList()
{
try
{
_ReadWriteLock.AcquireWriterLock(60000);
System.Collections.IDictionaryEnumerator dicEnum;
dicEnum = _CacheManager.GetEnumerator();
DataTable dtCache = new DataTable();
dtCache.Columns.Add("Key");
while (dicEnum.MoveNext() == true)
{
if (IsCacheable(dicEnum.Key.ToString()))
{
DataRow drCache = dtCache.NewRow();
drCache["Key"] = dicEnum.Key.ToString();
dtCache.Rows.Add(drCache);
}
}
return dtCache;
}
finally
{
//Release the write lock
if (_ReadWriteLock.IsWriterLockHeld)
{
_ReadWriteLock.ReleaseWriterLock();
}
}
}
// It retrieves a object from cache for a key
public static object RetrieveFromCache(EnumeratorsConfiguration.CacheKey key)
{
try
{
_ReadWriteLock.AcquireReaderLock(60000);
return _CacheManager.Get(key.ToString());
}
finally
{
if (_ReadWriteLock.IsReaderLockHeld)
{
_ReadWriteLock.ReleaseReaderLock();
}
}
}
/// Rerurns whether the specified key Exists in cache.
public static bool ExistsInCache(EnumeratorsConfiguration.CacheKey key)
{
try
{
if (_CacheManager.Get(key.ToString()) != null)
{
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
return false;
}
}
}
}

Now let us say I want to bind a dropdownlist by the values stored in the cache.Here is way how I can do thatHere we are taking an Enum for the Cache Key Settings. If there exists various Chache Key ,we can use an Enum for that

using System;
using System.Collections.Generic;
using System.Text;
namespace AppConfigurationManagement
{
public static class EnumeratorsConfiguration
{
#region Enum
public enum CacheKey
{
Location = 1,
Region =2,
Branch = 3
}
#endregion
}
}

Now let us call the Cache Methods.If the data for the specified cache key remains in the cache then we will call it ,otherwise we will add the value to the cache.

using System;
using System.Collections.Generic;
using System.Text;
using AppConfigurationManagement;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using BusinessEntity;
namespace BusinessLogic
{
public static class AppMetadataManager
{
#region Public Methods
/// Contains the methods for Metadata Management
public static object GetMetadata(EnumeratorsConfiguration.CacheKey key)
{
object metadata = null;
try
{
if (AppCacheManager.ExistsInCache(key) && ConfigurationManager.AppSettings["EnableCache"].ToString() == "1")
{
/*if the data is in cache returns that from the cache*/
metadata = AppCacheManager.RetrieveFromCache(key);
if (metadata == null)
metadata = GetMetadataFromDB(key);
}
else
{
metadata = GetMetadataFromDB(key);
}
}
catch (Exception e)
{
throw new Exception() ;
}
return metadata;
}
/// Flushes the Metadata
public static void FlushMetadata(EnumeratorsConfiguration.CacheKey key)
{
if (AppCacheManager.ExistsInCache(key))
{
AppCacheManager.RemoveFromCache(key);
}
}
private static object GetMetadataFromDB(EnumeratorsConfiguration.CacheKey key)
{
object metadata = null;
/*data is not in cache, so get the data from the database and put that in cache*/
switch (key)
{
case EnumeratorsConfiguration.CacheKey.Location:
DataSet dsLocation = BackEndManager.GetLocationList();
AppCacheManager.AddToCache(key, dsLocation);
metadata = dsLocation;
break;
case EnumeratorsConfiguration.CacheKey.Region :
List lstRegion = BackEndManager.GetRegionList();
AppCacheManager.AddToCache(key, lstRegion);
metadata = lstRegion;
break;
}
return metadata;
}
#endregion
}
}

Now in our Page_Load Event we can do the following
protected void Page_Load(object sender, EventArgs e)
{
ddlRegion.Items.Clear();
ddlRegion.Items.Add(new ListItem("---Select---", "0"));
List lstRegion = (List)MetadataManager.GetMetadata(ConfigurationEnumerators.CacheKey.Region);
foreach (Region objRegion in lstRegion)
{
ListItem li = new ListItem();
li.Text = objRegion.Name.ToString();
li.Value = objRegion.RegionID.ToString();
ddlRegion.Items.Add(li);
}
ddlRegion.DataBind();
}
I will post Upadte and Remove Cache very soon
However, the problem with the MS Caching application block is that it carries a lot of overhead and has a lot of features that may not be useful for your application








No comments: