Disposing SPRequest

by Danielvg 17. January 2011 22:20
I was recently asked about the disposing of SPRequest related objects like SPWeb and SPSite, since I was unsure on some of the questions I decided to do some small examples to determine when the following two errors related to disposing of SPRequest show in the ULC:
 
Error 1, Unexpected:
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.
 
Error 2, High:
An SPRequest object was not disposed before the end of this thread.  To avoid wasting system resources, dispose of this object or its parent (such as an SPSite or SPWeb) as soon as you are done using it.
 
 
Test case Result Id*
public void TestOne() 
{ 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (var web = site.OpenWeb()) 
    { 
        this.Literal1.Text = web.Title; 
    } 
}
Nothing  
public void TestTwo() 
{ 
    var site = new SPSite(SPContext.Current.Web.Url); 
    var web = site.OpenWeb(); 
    this.Literal1.Text = web.Title; 
}
Error 2
120
110
public void TestThree() 
{ 
    this.Literal1.Text = TestThreeHelper().Title; 
}


public SPWeb TestThreeHelper() 
{ 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (var web = site.OpenWeb()) 
    { 
        return web; 
    }
}
Error 1
 
public void TestFour() 
{ 
    var site = new SPSite(SPContext.Current.Web.Url); 
    using (var web = site.OpenWeb()) 
    { 
        site.Dispose(); 
        this.Literal1.Text = web.Title; 
    } 
}
Error 1
 
public void TestFive() 
{ 
    SPWeb web = null; 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (web = site.OpenWeb()) 
    { 
    } 
    this.Literal1.Text = web.Title; 
}
Error 1
 
public void TestSix() 
{ 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    { 
        var web = site.OpenWeb(); 
        this.Literal1.Text = web.Title + "test3"; 
    } 
}
Nothing
(SPSite disposes all sub webs, including rootWeb)
120
public void TestSeven() 
{ 
    SPList list = null; 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (var web = site.OpenWeb()) 
    { 
        list = web.Lists["SomeList"]; 
    } 
    this.Literal1.Text = list.Title; 
}
Error 1
 
public void TestEight() 
{ 
    SPListItem item; 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (var web = site.OpenWeb()) 
    { 
        var list = web.Lists["SomeList"]; 
        item = list.Items[0]; 
    } 
    this.Literal1.Text = item.Title; 
}
Nothing
(Some properties of SPListItem can be used, however other will reopen the Site, Web and list)
 
public void TestNine() 
{ 
    var site = new SPSite(SPContext.Current.Web.Url); 
    using (var web = site.OpenWeb()) 
    { 
        this.Literal1.Text = web.Title; 
    } 
}
Nothing
(I am pretty sure this will cause an Error 2 like problem when the thread that created the site ends)
110
public void TestTen() 
{ 
    using (var web = TestTenHelper()) 
    { 
        this.Literal1.Text = web.Title; 
    } 
}

public SPWeb TestTenHelper() 
{ 
    var site = new SPSite(SPContext.Current.Web.Url); 
    var web = site.OpenWeb(); 
    return web; 
}
Nothing
(Same as test nice)
120
110
*SPDisposeChecker warning id
I must admit that I am surprised about some of the results, but this at least clears everything up for me. Following is an example of how some of these errors can be resolved:
 
public void TestTreeFix() 
{ 
    Action<SPWeb> action = (openWeb) => { this.Literal1.Text = openWeb.Title; }; 
    TestTreeHelperFix(action); 
}

public void TestTreeHelperFix(Action<SPWeb> action) 
{ 
    using (var site = new SPSite(SPContext.Current.Web.Url)) 
    using (var web = site.OpenWeb()) 
    { 
        action(web); 
    } 
}
 
Dispose them objects! Else you will end up with no available ports and a starving farm!