The Best Practice Guidelines of Development on SharePoint 2010/SharePoint 2007 – Part 2

The Best Practice Guidelines of Development on SharePoint 2010/SharePoint 2007 - part 1

The Best Practice Guidelines of Development on SharePoint 2010/SharePoint 2007 – Part 2

Abstract:

This article describes how the objects are cached in the SharePoint2010 and the need to pay attention, but also introduces some of the technical optimization of the code.

Cache is the traditional. NET development of a common development approach to improve performance, but in SharePoint brought in to pay particular attention to the performance of the cache to improve the balance between and thread safe, some SharePoint objects are not thread-safe type, do Cache will lead to unexpected exception.

For example, when reading the list of data to cache SPListItemCollection is a common way of thinking, but because SPListItemCollection contains a non-secure threads SPWeb object, if the SPListItemCollection run directly to the cache will lead to error or abnormal operation.

The following example shows the cache SPListItemCollection not thread safe.

public void CacheData()
{
SPListItemCollection items;
items = (SPListItemCollection)Cache["AListItemCache"];
if(items == null)
{
items = DoQueryToReturnItems();
Cache.Add("AListItemCache", items, ...);
}
}







The code above working mechanism of the IIS is running multi-threaded, if DoQueryToResturnItems () query takes 10 seconds, in this time period, if a lot of users do the same operation, it will lead to the same query is also Run, and the object will be to modify the same items, it will not only result in thread-safe problems will also cause performance problems. In order to prevent the synchronization of multiple threads, you need to lock:




private static object _lock = new object();
public void CacheData()
{
SPListItemCollection items;
lock(_lock)
{
items = (SPListItemCollection)Cache["AListItemCache"];
if(items == null)
{
items = DoQueryToReturnItems();
Cache.Add("AListItemCache", items, ...);
}
}
}







In the above code, the location of the lock can be adjusted to  after if (items == null) and get a certain degree of performance improvement:




private static object _lock = new object();
public void CacheData()
{
SPListItemCollection items;
items = (SPListItemCollection)Cache["AListItemCache"];
if(items == null)
{
lock(_lock)
{
items = DoQueryToReturnItems();
Cache.Add("AListItemCache", items, ...);
}
}
}







But it also brings other problems, the implementation of this method when DoQueryToReturnItems long time when there may be multiple threads waiting outside in the lock, when the first thread is updating the Cache, the second thread will Incoming query data and update the thread, if there is a third thread will do the same thing. . . Can make the following improvements:




private static object _lock =  new object();

public void CacheData()
{
SPListItemCollection oListItems;
oListItems = (SPListItemCollection)Cache["ListItemCacheName"];
if(oListItems == null)
{
lock (_lock)
{
oListItems = (SPListItemCollection)Cache[“ListItemCacheName”];
if (oListItems == null)
{
oListItems = DoQueryToReturnItems();
Cache.Add("ListItemCacheName", oListItems, ..);
}
}
}
}







Although the above code to solve the cache problem, but the practice is still not recommended because it is a thread no-safe caching object SPListItemCollection. In order to solve the problem of thread no-safety, you can use DataTable to store data:




private static object _lock =  new object();

public void CacheData()
{
DataTable oDataTable;
SPListItemCollection oListItems;
lock(_lock)
{
oDataTable = (DataTable)Cache["ListItemCacheName"];
if(oDataTable == null)
{
oListItems = DoQueryToReturnItems();
oDataTable = oListItems.GetDataTable();
Cache.Add("ListItemCacheName", oDataTable, ..);
}
}
}







Code Optimization to SharePoint:



A common optimization:




SPWeb myWeb = SPContext.Current.Web;

myWeb.Lists["Tasks"].Title = "List_Title";
myWeb.Lists["Tasks"].Description = "List_Description";
myWeb.Lists["Tasks"].Update();







The following modified code is only one instance of a list of tasks and stored in the myList variable to reduce the access to the database to improve performance:




SPWeb myWeb = SPContext.Current.Web;

SPList myList = myWeb.Lists["Tasks"];

myList.Title="List_Title";
myList.Description="List_Description";
myList.Update();