Suppose We Don’t Dispose

As SharePoint developers, we all know that we have to Dispose our SPSite and SPWeb instances if we didn’t acquire them from the SPContext. If you don’t know what I’m talking about, STOP and go to Roger Lamb's blog read and understand.  
   
Now I’ll show you how I used to code to be sure to “never” leak any SharePoint resources. I created a utility class with (among others) a method called GetList( string webUri, string listName ) see below.  
public SPList GetList( string webUri, string listName )
{
    using (SPSite site = new SPSite(webUri))
    {
        using (SPWeb web = site.OpenWeb())
        {
            return web.Lists[listName];
        }
    }
}
 
What is wrong with this method? I acquire the SPSite and SPWeb objects and then dispose of them, returning the SPList….  
   
The problem is that we shouldn’t be able to use the SPList when the parent SPWeb has been disposed…. UNFORTUNATELY MS has put a lot of compensating logic into the Object Model to manage this instead of just throwing an ObjectDisposed exception. So if you you use this returned SPList instance what will happen is that the Object Model will instantiate a new SPWeb and you will leak this since the SPList does not implement IDisposable. If you turn on verbose logging you will see entries like this one below when WSS detects that you are using a disposed SPWeb.  

Detected use of SPRequest for previously closed SPWeb object. Please close SPWeb objects when you are done with all objects obtained from them, but not before Stack trace:

 
So let’s look at my current favorite “pattern”. I use delegates so that I know that the lifetime of my SPSite and SPWeb are managed properly. This is the equivalent of a method called GetSPWeb( string uri );  
   
public void WithWeb(string uri, Action<SPWeb> action)
{
    using (SPSite site = new SPSite(uri))
    {
        using (SPWeb web = site.OpenWeb())
        {
            action(web);
        }
    }
}
 
Let’s take a look at the call site:  
   
public void WithList(string webUri, string listName, Action<SPList> action)
{
    WithWeb(webUri, delegate(SPWeb web)
    {
        foreach (SPList list in web.Lists)
        {
            if (list.RootFolder.Name == listName)
            {
                action(list);
                break;
            }
        }
    });
}
 
As you can see, all instances are alive until the delegate has executed, then they are disposed of in the correct order.  

Disclaimer: There are so many interdependencies in the SharePoint object model so the above delegates won’t fix “everything” but the main point I want to get through is DON’T work with disposed objects or descendents of them.

 

/Jonas

 

Posted Sep 29 2009, 05:47 PM by Jonas Nilsson

Comments

Oliver Wirkus wrote Potentielles Memory-Leak beim Suchen nach Listen
on Thu, Sep 15 2011 2:12 AM

Jeder der schon für SharePoint entwickelt hat, wird sicher schon öfter eine änliche Methode geschrieben

Add a Comment

Please sign into Bamboo Nation to leave a comment.

Blogs

    The Bamboo Team Blog
  • Home

Bamboo Nation, Media Sponsor of:

SPTechCon

Subscribe by Email

Syndication

Bamboo Nation Almost Everywhere

Follow Bamboo Nation on:Bamboo Solutions on Facebook

Bamboo Solutions on Google+

Bamboo Solutions on LinkedIn

Bamboo Solutions on Twitter

Bamboo Solutions on YouTube

Bamboo Now in Alltop!

        Featured in Alltop

SharePoint Calendars

SharePoint Calendars

Bamboo Solutions Corporation, 2002-2012