Wednesday, August 03, 2005 9:57 PM
hannes
Caching Paladin entity lists in ASP .net
A good way to improve performance in web applications is to cache entity lists. This reduces access to the database greatly.
If the cached copy is used carefully, it can be kept "fresh" and concurrency issues can be kept to a minimum without resolving to thread locking etc.
Whenever access to the entity list is required, a method/property such as the following can be called. In this example the object will expire in at least 10 minutes. If your database is not updated from another application and you are confident that you are correctly managing your cache, you may want to increase this time.
public epcdb.SupplierList GetSupplierList()
{
epcdb.SupplierList lst = Cache["SupplierList"] as epcdb.SupplierList;
if (lst == null)
{
lst = new epcdb.SupplierList();
BusinessComponent BC = new BusinessComponent();
BC.Populate(lst);
lst.Sort = epcdb.Supplier.FieldNames.name;
Cache.Add("SupplierList",
lst,
null,
DateTime.Now.AddMinutes(10),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.High,
null);
}
return lst;
}
Be careful when your code relies on the list to stay the same. This may seem harmless:
int idx = GetSupplierList().Find("id", 123);
Supplier = GetSupplierList()[ idx ];
However, in a multi-user, multi-threaded environment, the cached entity list could have expired and the second call to SupplierList would then return a new entity list. There is a very slim chance, but within the nanosecond, the index could be pointing to a different entity which could cause a serious glitch.
Of course using the primary key of the entity would solve this particular issue, but other glitches could occur when cached lists expire. To be sure, obtain a reference to the entity list instead, as the Singleton pattern suggests:
epcdb.SupplierList SupplierList = GetSupplierList();
int idx = SupplierList.Find("id", 123);
Supplier = SupplierList[idx];
Now the only thing that could still potentially cause a glitch, is if other threads modify (Add/Edit/Remove) the cached list. So don't do this. Rather perform updates with Paladin without using the cached list, then expire the cached list, as follows:
epcdb.Supplier Supplier = new epcdb.Supplier(123);
Supplier.name = "Lukes Light Sabres";
Supplier.MarkForUpdate();
BusinessComponent BC = new BusinessComponent();
BC.Save(Supplier);
Cache.Remove("SupplierList"); // do this after Adding/Editing/Removing
Besides expiring SupplierList, all other cached items that could have been affected (eg. via a cascaded delete) should be expired. Instead of carefully expiring all affected items, you could also create a dependency to the cached SupplierList when caching the other items, eg:
Cache.Add("InventoryList",
inventorylist,
new System.Web.Caching.CacheDependency(
null, new string[] { "SupplierList" }), // Also expire when SupplierList expires.
DateTime.Now.AddMinutes(60),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.High,
null);
This will cause InventoryList to expire whenever SupplierList expires.
Filed under: ASP .net, Paladin, Software development