Introduction
When using the Windows Communication Framework (WCF) or Remoting, one of the issues developers have to deal with is degraded performance because of chatty interfaces. To deal with this, I have developed a method to store data that is generally static on the client to reduce calls to the server side for this data. The key to the method is that your objects and WCF calls do not need to know about this caching, it is all done in the WCF client code right before a call to the server is made.
I will demonstrate this method with a simple WCF application that pulls data from the Categories
table of Northwind
and caches these categories on the client side. When a call is made to retrieve the category by id, it does not have to make a call to the server, it can just pull the data from the client side cache.
Note: I came up with this solution while working to improve performance in a WinForms (Smart Client) application that was experiencing performance problems. I found the root cause of the performance issues to be too many calls to the database. The original implementation was done with Remoting rather than WCF.
Using the Code
This method involves using a Singleton to store the data on the client side. Data in the Singleton is accessed using events in the WCF client because the client is in a different project than the Singleton.
To enable the client to retrieve data from the client side cache, check to see if the event is not null and then fire the event using the custom event args containing the search parameter and also containing a way to pass the result back. If the object is not found locally, then the client will make a call to the server to find it there.
The WCF Client method to find the Category by an Id:
public event FindObjectByIdInvokedDelegate GetCategoryByIdInvoked;
public Category GetCategoryById(int id)
{
Category cat = null;
if (GetCategoryByIdInvoked != null)
{
FindObjectByIdEventArgs args = new FindObjectByIdEventArgs(id);
GetCategoryByIdInvoked(this, args);
cat = args.FoundObject as Category;
}
if (cat == null)
{
cat = base.Channel.GetCategoryById(id);
}
return cat;
}
The Singleton class with WCF client event hooked up:
public Client WcfClient
{
get{
if (wcfClient == null)
{
wcfClient = new Client();
wcfClient.GetCategoryByIdInvoked +=
new FindObjectByIdInvokedDelegate(wcfClient_GetCategoryByIdInvoked);
}
return wcfClient;
}
}
void wcfClient_GetCategoryByIdInvoked(object sender, FindObjectByIdEventArgs args)
{
foreach (Category cat in Categories)
{
if (cat.CategoryID == args.SubjectId)
args.FoundObject = cat;
}
}
Conclusion
This is a pretty simple example, but this can be expanded fairly easily to include any type of data. By doing this in a large smart client application, we saw huge performance increases by reducing calls to the server. I would highly recommend anyone looking to increase performance in a smart client application to look into implementing a process similar to this.
History
- 1/31/2008 - Initial version