Tuesday, February 1, 2011

The Disposable in SharePoint Development

If you don’t properly dispose of objects in the SharePoint object model that implement IDisposable, you will have memory usage problems in your application. The objects to be most careful of are SPSite and SPWeb, which must be disposed of because they consume large amounts of unmanaged memory.

But Wait… I Thought Garbage Collection Took Care of Memory Management?

The answer to this question is that an object like SPSite uses a mix of managed and unmanaged code. The memory usage of the managed side of SPSite is monitored by the .NET garbage collector, and when enough memory is used by the managed code, the garbage collector will kick in. The problem is that the .NET garbage collector doesn’t watch the unmanaged code’s use of memory and the unmanaged memory use is much greater than the managed memory use. So you can quickly run out of memory on the unmanaged
side without .NET ever feeling like it needs to do a garbage collection.

There are several coding patterns that I use when working with SPWeb and SPSite and other objects that implement IDisposable, so I would like to share with all of you:

Using Dispose with SPSite or SPWeb  object

SPSite oSite = new SPSite("http://localhost");

// Do something

SPWeb oWeb = oSite.OpenWeb();

// Do something

oWeb.Dispose();
oSite.Dispose();

The using clause with SPSite or SPWeb

using (SPSite oSite = new SPSite("http://localhost"))
{
    // Do something
    using (SPWeb oWeb = oSite.OpenWeb())
    {
        // Do something
    }
}

Using Dispose in the finally block of try, catch, finally code

SPSite oSite = null;
SPWeb oWeb = null;
try
{
    if ((oSite = new SPSite("http://localhost")) != null)
    {
        oWeb = oSite.OpenWeb();
        // Do something
    }
}
catch (Exception ex)
{
    // Handle exception
}
finally
{
    if (oWeb != null)
        oWeb.Dispose();

    if (oSite != null)
        oSite.Dispose();
}

Using Dispose with an object in a foreach loop

using (SPSite oSite = new SPSite("http://localhost"))
{
    foreach (SPWeb oWeb in oSite.AllWebs)
    {
        try
        {
            // Do something here
        }
        catch (Exception ex)
        {
            // Handle exception
        }
        finally
        {
            if (oWeb != null)
                oWeb.Dispose();
        }
    }
}

Do Not Dispose of the SPSite and SPWeb Return By SPContext

According to SharePoint best practices, SPSite and SPWeb objects returned by SPContext.Site, SPContext.Current.Site, SPContext
.Web, and SPContext.Current.Web should not be explicitly disposed by user code.

SharePoint Dispose Checker Tool

Alternatively, you can use SPDisposeCheck to measure your code against known Microsoft dispose best practices.

No comments: