The Windows SharePoint Services (WSS) 3.0 object model, provides a set of classes to work with WSS data. These objects can be used to read and write data to the WSS store. The WSS object model contains many objects that implement the
IDisposable interface, which primary use is to release unmanaged resources. The Dispose method of IDisposable is intended to be called by consumers of the object, directly or with the
using statement, in order to release unmanaged resources.
Best Practices for Disposing WSS objectsTwo common WSS objects that implement IDisposable are
SPSite and
SPWeb. SPSite represents a site collection, and SPWeb represents a single site. A common mistake is to use these objects without disposing unmanaged resources:
// BAD: SPSite and SPWeb will be leaked.
SPSite site = new SPSite("http://server");
SPWeb web = site.OpenWeb();
string title = web.Title;
string url = web.Url;
A better way to write the code above is:
// GOOD: No leaks.
using(SPSite site = new SPSite("http://server"))
{
using(SPWeb web = site.OpenWeb())
{
string title = web.Title;
string url = web.Url;
}
}
The code above was very simple, but you got the idea. Things start getting more complicated when you start combining calls into the same line. This makes harder to catch leaks, since you do not see the implicit referenced object. For example:
// BAD
SPWeb web = new SPSite("http://server").OpenWeb();
The line above, might make you thing that there is only one leak, and you will attempt to fix with the following:
// BAD
using (SPWeb web = new SPSite("http://server").OpenWeb())
{
...
}
The code above will dispose the SPWeb object that is returned by the OpenWeb method, but it will not dispose the SPSite that is created by the new operator. The solution is the same as the first problem:
// GOOD: No leaks.
using(SPSite site = new SPSite("http://server"))
using(SPWeb web = site.OpenWeb())
{
...
}
Working with SharePoint collections also need some attention. When using
SPWebCollection objects, you will need to dispose any SPWeb object that is accessed using the [] indexer or with a
foreach statement. The same applies for
SPSiteCollection. The following code shows how to avoid leaks when using the SPSiteWeb object:
// GOOD: No leaks.
using (SPSite site = new SPSite("http://server"))
{
using (SPWeb web = siteCollection.OpenWeb())
{
foreach (SPWeb innerWeb in site.AllWebs)
{
try
{
// ...
}
finally
{
// Must dispose the collection item.
if(innerWeb != null)
innerWeb.Dispose();
}
}
}
}
A similar approach would be used if you were accessing collection items using the [] indexer. You would need to dispose each object returned by [].
The examples above just show you a few common cases of how to dispose WSS objects, just for you to get the idea. The following article provides detailed explanation of how to detect and proper dispose your SharePoint objects:
You can also look at Roger Lamb's article which complements the article above with lots of examples:
SPDisposeCheck ToolThe
SPDisposeCheck tool analyzes your assembly and detect if you are disposing WSS objects properly. This tool
takes the path to a managed .DLL or .EXE, or the path to a directory containing many managed assemblies. It will recursively search for and analyze each managed module attempting to detect coding patterns based on best practice article above. The tool does not detect all possible unmanaged resources leaks, so you still have to learn the
best practices and review your code.
You can install SPDisposeCheck from
here. It is a console application, and you should add
C:\Program Files\Microsoft\SharePoint Dispose Check to your path.
The usage is:
SPDisposeCheck -debug –xml
The output is a list of potential problems. If you have the PDB symbol file available, then the output will include additional source code information about the error. The
-debug option adds additional information to the output. The
-xml option outputs the errors to an XML file instead of text, however,
the SPDisposeCheck site says that this option is unreliable, and they do not recommend to use this command on this release.I run this tool with a WebPart that I recently created, and I got the following result:
ID: SPDisposeCheckID_160
Module: CustomCalendar.dll
Method: CalendarGenerator.SharePointCalendarRepository.#ctor(System.String)
Statement: manager := web.{Microsoft.SharePoint.SPWeb}GetLimitedWebPartManager(pageUrl, 1)
Source: D:\Code\CustomCalendar\CustomCalendar\SharePointCalendarRepository.cs
Line: 40
Notes: Dispose/Close was not called on SPLimitedWebPartManager.Web
More Information: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_160
----------------------------------------------------------
Total Found: 1
Well, although I am embarrassed that it found a bug in my code, I am very glad that this tool works! In my code, I am calling
GetLimitedWebPartManager which returns a
SPLimitedWebPartManager. This returned reference also needs to be disposed.
The following table contains the possible errors, links to the detailed description, and a summary of the solution.
The tool also allows you to ignore a reported issue. If you have investigated a reported issue and are satisfied that it does not represent a problem, then you can add the following attribute to the calling method:
[SPDisposeCheckIgnore(SPDisposeCheckID.SPDisposeCheckID_100, "Ignoring this error")]
To add this attribute to your method, you will need to grab the source code of the attribute class from the file:
C:\Program Files\Microsoft\SharePoint Dispose Check\SPDisposeExamplesSource.zip
One of things to consider, is to run SPDisposeCheck Tool as a post-build event of your assembly. If it reports any issue, then the build fails. Developers can then detect leak problems at build time and troubleshoot them as soon as possible.
ConclusionThe improper memory management of WSS objects can lead to a poor system performance, system crash, or users experiencing unexpected errors (timeouts, page not available), especially under heavy loads. To avoid these problems, developers need to follow
best practices for disposing WSS objects, and also use tools, such as
SPDisposeCheck, to check if their assemblies are properly disposing WSS objects.
References