Roger Lamb's SharePoint Developer Blog

SharePoint 2007 and WSS 3.0 Dispose Patterns by Example

Overview

Windows SharePoint Services (WSS 3.0) and Microsoft Office SharePoint Server (MOSS 2007) have some gotchas with serious implications that every SharePoint application developer needs to be intimately familiar with before deploying into production MOSS 2007 farms.  In particular, Microsoft.SharePoint.SPSite , Microsoft.SharePoint.SPWeb , and the often overlooked (MOSS 2007) Microsoft.SharePoint.Publishing.PublishingWeb objects need to be carefully examined and disposed of properly in order to avoid potential memory leaks.

My objective with this blog post was to consolidate several sources compiled by Microsoft's top subject matter experts into a simplified quick reference format which can be used to increase awareness as well as jump start into a SharePoint custom code review. Look for a follow-up post where I will do a high level walk-through using the windows debugger (windbg) to help identify common SharePoint memory leaks.

Note: This Blog will be updated periodically as new dispose leak guidance are released.

Why Dispose?

SPSite and SPWeb classes both implement the IDisposable interface.  Microsoft .NET requires objects that implement the IDisposable interface to properly cleanup the unmanaged resources by explicitly calling the Dispose() method when you are finished using them.  Internally, SPSite and SPWeb both hold references to an "internal class Microsoft.SharePoint.Library.SPRequest" which holds on to unmanaged COM resources.  The consequence of not explicitly disposing unmanaged resources in a timely fashion can lead to not having enough memory for further allocations and quickly consumes memory. Under the hood, when reviewing dump files we see the that the managed objects used by SPSite and SPWeb are relatively small and it's the unmanaged resources that are most concerning and account for approximately 1MB to 2MB for each object instance!  Omitting to explicitly call Dispose() means the .NET (non-deterministic) garbage collector gets out of sync with the finalizer and the unmanaged memory does not get reclaimed in a timely manner possibly blocking future memory allocations. For further reading I recommend reviewing Stefan Goßner's blog Dealing with Memory Pressure problems in MOSS/WSS .

The unmanaged memory leaks can grow very quickly especially when traversing through frequently called areas like site navigation code and item event receivers.  The lack of proper Dispose() hygiene can increase your risk of frequent IIS Application Domain recycles (see Steve Sheppard's blog Overlapped Recycling And SharePoint: Why SharePoint Requires It), Out Of Memory (OOM) exceptions, high memory consumption, and poor performing SharePoint production environments.

To Dispose or not Dispose?! That is the question...

To make matters more confusing for SharePoint developers there are times when SPSite and SPWeb objects should not be disposed and are cleaned up by SharePoint and ASP.NET after page processing is completed.  In addition, there are cases when developers indirectly call a property on a object that creates and holds an internal reference to a SPSite or SPWeb object (for example SPSite.RootWeb property).  Understanding the origin and the scope the object was created is paramount when determining whether or not to explicitly call dispose.

Dispose Patterns

When writing customized SharePoint code you need to be aware of the scope and context of each SPSite, SPWeb, and PublishingWeb objects lifetime.  When objects are created and destroyed in the same method or iteration scope (foreach or do/while loop) they are the easiest to clean handle.  Things become more complex to review when developers create objects in one method and dispose in another.  Areas to be aware of are assigning objects to class variables or static/global variables which may hold on to the object reference across method calls.

With that said, below are the Dispose most common patterns you need to be aware of when developing customized SharePoint code.

Microsoft.SharePoint.SPList.BreakRoleInheritance (Added 4/11/08)


void SPListBreakRoleInheritanceLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPList list = web.Lists["ListName"];
            list.BreakRoleInheritance(true);
            // SPWeb list.ParentWeb leaked here, requires call to list.ParentWeb.Dispose()
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void SPListBreakRoleInheritanceBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPList list = web.Lists["ListName"];
            list.BreakRoleInheritance(true);
            list.ParentWeb.Dispose(); // Best practice 
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

Microsoft.SharePoint.WebPartPages.SPLimitedWebPartManager


void SPLimitedWebPartManagerLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
            SPLimitedWebPartManager webPartManager =
                page.GetLimitedWebPartManager(PersonalizationScope.Shared);
            // SPWeb object webPartManager.Web leaked
        } // SPWeb object web.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void SPLimitedWebPartManagerBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
            using (SPLimitedWebPartManager webPartManager = 
                page.GetLimitedWebPartManager(PersonalizationScope.Shared))
            {
                webPartManager.Web.Dispose();
            }
        } // SPWeb object web.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

Microsoft.SharePoint.Publishing.PublishingWeb (MOSS 2007 Only)


void PublishingWebCollectionLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);

            PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
            foreach (PublishingWeb innerPubWeb in pubWebCollection)
            {
                // innerPubWeb leak
            }
        } // SPWeb object web.Dispose() automatically called
    } // SPSite object siteCollection.Dispose() automatically called
}

void PublishingWebCollectionBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);
            PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
            foreach (PublishingWeb innerPubWeb in pubWebCollection)
            {
                // innerPubWeb referenced so we must call outerPubWeb.Close()
                // otherwise, we will leak each and every innerPubWeb object
                innerPubWeb.Close();
            }
        }  // SPWeb object web.Dispose() automatically called
    } // SPSite object siteCollection.Dispose() automatically called
}

void GetPublishingWebBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
            // As long as you are not using the collection you don't have
            // to call singlePubWeb.Close() explicitly
            PublishingWeb singlePubWeb = PublishingWeb.GetPublishingWeb(web);
        } // SPWeb object web.Dispose() automatically called
    } // SPSite object siteCollection.Dispose() automatically called
}

Microsoft.SharePoint.Publishing.PublishingWebCollection (MOSS 2007 Only)


  • When using the PublishingWebCollection class GetPublishingWebs().Add() method you are required to call close on the newly added PublishingWeb object.  For a code sample refer to the MOSS SDK GetPublishingWebs() sample.

Microsoft.SharePoint.SPSite


  • new SPSite() - Instantiating SPSite objects with the new operator needs to be disposed.

Note: With C# you can automatically have the Dispose() called for you when the object leaves the scope by wrapping the code with the using() { } statement.

void CreatingSPSiteLeak()
{
    SPSite siteCollection = new SPSite("http://moss");
    // siteCollection leaked
}

void CreatingSPSiteExplicitDisposeBestPractice()
{
    SPSite siteCollection = new SPSite("http://moss");
    siteCollection.Dispose();
}

void CreatingSPSiteWithAutomaticDisposeBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
    } // SPSite object siteCollection.Dispose() automatically called
}

Avoid the following pattern which collapses SPSite and SPWeb calls.  The example returns the SPWeb site object wrapped by a using statement which gets disposed but there is no way to dispose the underlying SPSite object.

void OpenWebLeak()
{
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
        // SPSite leaked !
    } // SPWeb object web.Dispose() automatically called
}

void OpenWebBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        } // SPWeb object web.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called
}
  • RootWeb property returns a SPWeb object that needs to be disposed.
void RootWebLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb siteRootWeb = siteCollection.RootWeb; // Internal reference to SPWeb siteRootWeb
        string sTitle = siteRootWeb.Title; 
        string sUrl = siteRootWeb.Url;
        // siteRootWeb leaked (once)
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void RootWebBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb siteRootWeb = siteCollection.RootWeb) // Internal reference to SPWeb siteRootWeb
        {
            string sTitle = siteRootWeb.Title;
            string sUrl = siteRootWeb.Url;
        } // SPWeb object siteRootWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}
  • LockIssue property indirectly creates a instance of SPWeb object on the RootWeb property which needs to be disposed.
void LockIssueLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        string strLockIssue = siteCollection.LockIssue;
        // siteCollection.RootWeb leaked
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void LockIssueBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        string strLockIssue = siteCollection.LockIssue;
        siteCollection.RootWeb.Dispose();
    }  // SPSite object siteCollection.Dispose() automatically called 
}
  • Owner property indirectly creates a instance of SPWeb object on the RootWeb property which needs to be disposed.
void OwnerLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPUser ownerUser = siteCollection.Owner;
        // siteCollection.RootWeb leaked
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void OwnerBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPUser ownerUser = siteCollection.Owner;
        siteCollection.RootWeb.Dispose();
    }  // SPSite object siteCollection.Dispose() automatically called 
}
void SecondaryContactLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPUser secondaryContactUser = siteCollection.SecondaryContact;
        // siteCollection.RootWeb leaked
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void SecondaryContactBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPUser secondaryContactUser = siteCollection.SecondaryContact;
        siteCollection.RootWeb.Dispose();
    }  // SPSite object siteCollection.Dispose() automatically called 
}
void AllWebsForEachLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                // innerWeb leak
            }
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void AllWebsForEachBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                innerWeb.Dispose();
            }
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void AllWebsIndexerLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb web = siteCollection.AllWebs[0];
        // SPWeb web leaked
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void AllWebsIndexerBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.AllWebs[0])
        {
        } // SPWeb object web.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}
void AllWebsAddLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb web = siteCollection.AllWebs.Add("site-relative URL");
        // SPWeb web Leaked
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void AllWebsAddBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
        {
        } // SPWeb object web.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

Microsoft.SharePoint.SPWeb


void ParentWebLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            SPWeb parentWeb = outerWeb.ParentWeb; // Internal reference to SPWeb parentWeb
            string sTitle = parentWeb.Title; 
            string sUrl = parentWeb.Url; 
            // SPWeb object parentWeb leaked
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void ParentWebBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            using (SPWeb parentWeb = outerWeb.ParentWeb) // Internal reference to SPWeb parentWeb
            {
                string sTitle = parentWeb.Title;
                string sUrl = parentWeb.Url;
            } // SPWeb object parentWeb.Dispose() automatically called
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}
void WebsLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                // SPWeb innerWeb leak
            }
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

void WebsBestPractice()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                innerWeb.Dispose();
            }
        } // SPWeb object outerWeb.Dispose() automatically called
    }  // SPSite object siteCollection.Dispose() automatically called 
}

Microsoft.SharePoint.WebControls.SPControl

void SPControlBADPractice()
{
    SPSite siteCollection = SPControl.GetContextSite(Context);
    siteCollection.Dispose();   // DO NOT DO THIS
    SPWeb web = SPControl.GetContextWeb(Context);
    web.Dispose();  // DO NOT DO THIS
}

void SPControlBestPractice()
{
    SPSite siteCollection = SPControl.GetContextSite(Context);
    SPWeb web = SPControl.GetContextWeb(Context);
    // Do NOT call Dispose()
}

Microsoft.SharePoint.SPContext

void SPContextBADPractice()
{
    SPSite siteCollection = SPContext.Current.Site;
    siteCollection.Dispose(); // DO NOT DO THIS
    SPWeb web = SPContext.Current.Web;
    web.Dispose(); // DO NOT DO THIS
}

void SPContextBestPractice()
{
    SPSite siteCollection = SPContext.Current.Site;
    SPWeb web = SPContext.Current.Web;
    // Do NOT call Dispose()

    // 2nd Best Practice example which demonstrates combining calls in same scope
    using (SPWeb webRoot = SPContext.Current.Site.RootWeb)
    {
        // SPSite is ok since it came from SPContext and
        // RootWeb will be disposed automatically by C# using statement
        // this is a fairly common pattern to keep an eye out for
    }
}

Microsoft.SharePoint.Administration.SPSiteCollection

void SPSiteCollectionIndexerLeak()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;

    SPSite siteCollection = siteCollections[0];
    // SPSite siteCollection leak 
}

void SPSiteCollectionIndexerBestPractice()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;

    SPSite siteCollection = siteCollections[0];
    siteCollection.Dispose();
}

void SPSiteCollectionForEachLeak()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;

    foreach (SPSite siteCollection in siteCollections)
    {
        // SPSite siteCollection leak
    }
}

void SPSiteCollectionForEachBestPractice()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;

    foreach (SPSite siteCollection in siteCollections)
    {
        siteCollection.Dispose();
    }
}
  • Add() returns a SPSite object which needs to be disposed.
void SPSiteCollectionAddLeak()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;
    SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection",
        "DOMAIN\\User", "roger.lamb@litwareinc.com");
    // SPSite siteCollection leak
}

void SPSiteCollectionAddBestPractice()
{
    SPWebApplication webApp = new SPSite("http://moss").WebApplication;
    SPSiteCollection siteCollections = webApp.Sites;
    using (SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection",
        "DOMAIN\\User", "roger.lamb@litwareinc.com"))
    {
    } // SPSite object siteCollection.Dispose() automatically called
}

Microsoft.SharePoint.Portal.SiteData.Area.Web (Obsolete)


  • Area.Web property returns a SPWeb object which will need to be disposed.  Although classes Area and AreaManager are now obsolete in MOSS 2007 it is still of concern when migrating legacy code.
void AreaWebLeak()
{
    // AreaManager and Area are obsolete in MOSS but this should still be noted
    Area area = AreaManager.GetArea(PortalContext.Current, new Guid("{GUID}"));
    string str = area.Web.Title;
    // SPWeb area.Web leak
}

void AreaWebBestPractice()
{
    // AreaManager and Area are obsolete in MOSS but this should still be noted
    Area area = AreaManager.GetArea(PortalContext.Current, new Guid("{GUID}"));
    string str = area.Web.Title;
    area.Web.Dispose();
}

Cross Method Dispose Patterns

  • The following example demonstrates the common practice of holding onto the SPSite and SPWeb objects across methods in a class.  There are times where this design pattern is required however make sure you don't overlook the appropriate time to call dispose when you are finished with the cross method calls.  Below is an example of this pattern and shows and example of a leak of both SPSite and SPWeb when the class is torn down.
public class CrossMethodLeak
{
    private SPSite _siteCollection = null;
    private SPWeb _web = null;

    public void MethodA()
    {
        _siteCollection = new SPSite("http://moss");
        _web = _siteCollection.OpenWeb();
    }

    public void MethodB()
    {
        if (_web != null)
        {
            string title = _web.Title;
        }
    }

    public void MethodC()
    {
        if (_web != null)
        {
            string name = _web.Name;
        }
    }
}

Summary

If you have extended MOSS 2007 or WSS 3.0 with custom code you should digest this post carefully to avoid expensive consequences commonly found in production environments.  For a more verbose explanation of many of the topics covered in this blog post I suggest you read Scott Harris's MSDN White Papers Best Practices: Using Disposable Windows SharePoint Services Objects and Best Practices: Common Coding Issues When Using the SharePoint Object Model .

Special thanks to my Microsoft colleagues Scott Harris, Stefan Goßner, Steve Sheppard, Sean Thompson, Lisa Guthrie, Cliff Green, and Rick Caudle for reviewing and helping contribute to this blog post.

Published Tuesday, February 12, 2008 9:42 PM by Roger Lamb

Comments

 

MSDN Blog Postings » SharePoint 2007 and WSS 3.0 Dispose Patterns by Example said:

February 12, 2008 10:00 PM
 

Christopher Steen said:

Sharepoint SharePoint 2007 and WSS 3.0 Dispose Patterns by Example [Via: Roger Lamb ] WPF WPF 3.5 Data...

February 13, 2008 8:35 AM
 

Don Smith said:

My good friend Roger Lamb has just joined the blogsphere and I assure you that if you are interested

February 13, 2008 12:38 PM
 

arangas said:

Hi Roger,

This article is a good reference as it covers more than the MSDN best practices article. It would be great to see this post updated as you think of more information. I noticed that you don't mention (not) disposing when using SPContext, which would be a good addition (and what about cases such as SPContext.Current.Site.RootWeb?). Using the ULS logs to find which parts of your code aren't disposing correctly would be great too.

Thanks again, Alex.

February 14, 2008 10:17 AM
 

Steve Sheppard's Blog said:

For his first post he has provided a bunch of examples of dispose patterns for SharePoint that will be

February 15, 2008 12:45 PM
 

Noticias externas said:

For his first post he has provided a bunch of examples of dispose patterns for SharePoint that will be

February 15, 2008 12:53 PM
 

Miguel Isidoro said:

When developing for the SharePoint platform, developers should be very careful in using the SharePoint

February 20, 2008 3:35 PM
 

MaximeB said:

Very good job detailing a lot more the default principles on disposing objects.

Maxime

February 21, 2008 11:38 AM
 

The Mit's Blog said:

Un post qui vient un poil en doublon de ceux qui relaye 2 nouveaux articles de blog mais ces posts sont

February 25, 2008 10:19 AM
 

Blog del CIIN said:

Hacía tiempo que no revisaba mis RSS sobre SharePoint , y claro me ha costado ponerme al día, y aquí

February 25, 2008 7:00 PM
 

Mirrored Blogs said:

A very good article about Sharepoint 2007 and WSS 3.0 Dispose Patterns: Roger Lamb's SharePoint Developer

March 5, 2008 1:02 AM
 

bazztrap said:

Basically any new instance has to be disposed, I am curious about objects which are referenced from different events like  EvenHandler properties properties.OpenWeb()  

March 24, 2008 11:26 AM
 

Mirrored Blogs said:

Tipps Sending alerts to groups in Sharepoint 2007 SharePoint 2007 Permissions Matrix What is ReGhost

April 1, 2008 3:44 AM
 

Random Musings of Jeremy Jameson said:

Back in February, Roger Lamb kicked off his MSDN blog with a great post ( SharePoint 2007 and WSS 3.0

April 9, 2008 2:45 PM
 

Roger Lamb's SharePoint Developer Blog said:

I updated my MSDN blog post titled SharePoint 2007 and WSS 3.0 Dispose Patterns by Example with a recently

April 11, 2008 12:55 AM
 

Christophe Fiessinger's Blog said:

A week ago I pointed to a sample piece of code to retrieve Project Server Settings , today I came across

April 11, 2008 5:55 PM
 

Chris White said:

What about feature handlers e.g. feature activation handler.

If the feature is a site collection feature I have code of the type:

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

   using (SPSite site = properties.Feature.Parent as SPSite)

   {

   }

}

Am I correct in disposing the SPSite object here from the properties parameter ?!

April 15, 2008 5:50 AM
 

stkaye said:

You also need to be careful with RootWeb property on the SPSite object returned from the SPControl / SPContext objects.

If your current context’s web is the root web of you current context’s site then the RootWeb property of the site will reference the same object return by SPControl.GetContextWeb and SPContext.Current.Web and should therefore not be disposed.

E.g.

SPSite site = SPControl.GetContextSite(HttpContext.Current); // Don't dispose

using (SPWeb web = site.RootWeb)

{

 url = web.Url;

} // automatically disposed

This works fine in subwebs but not in the root web because when at the root wev it disposes the context web object as they reference the same object.

This is also the case if you used the following line to declare and intialise your site variable.

SPSite site = SPContext.Current.Site; // Don't dispose

Suggested best practice

SPSite site = SPContext.Current.Site; // Don't dispose

SPWeb web = site.RootWeb;

if (SPContext.Current.Web != web)

web.Dispose();

April 15, 2008 11:09 AM
 

rlasker3 said:

I also want to know about the SPFeature.Parent. I have seen arguments either way and would prefer something a little definitive.

April 17, 2008 9:54 AM
 

SaurabhKV said:

When writing customized SharePoint code you need to be aware of the scope and context of each SPSite

May 6, 2008 3:03 AM
 

buzza said:

Microsoft.SharePoint.SPList.BreakRoleInheritance.

Consider this:

To get a SPList object, you need to have a SPWeb object (is there any other way?), wouldn't that be the same (reference as well) as the SPList.ParentWeb object.  Now if this SPWeb object came from the current context then it should not be disposed.  If the SPWeb object was not created by the current context then it should be disposed.

using (SPSite mySite = new SPSite("http://server"))

using (SPWeb myWeb = mySite.OpenWeb())

{

     SPList myList = myWeb.Lists[0];

     // is myList.ParentWeb always the same reference as myWeb

     // if not - what circumstances is it not.

     // if so - parentweb is disposed with the using statement

}

Are we sure we need to dispose SPList.ParentWeb ???

Is this correct ??

May 9, 2008 11:18 PM
 

Stian Kirkeberg said:

Great article, Robert! Thank you.

What do you think should be the best way to handle a situation like this:

using (SPSite mySite = new SPSite("http://server"))

using (SPWeb myWeb = mySite.OpenWeb())

{

     myMethod(myWeb);

}

private void myMethod(SPWeb web)

{

     // work with the web object

    // should dispose be called? What about the reference copy on the stack?

}

And situation 2:

private void myMethod(SPWeb web)

{

     // work with the web object

    mySite.OpenWeb()) // then open another web....

    // call dispose.

}

Do you agree? Or can you suggest another pattern to avoid these situations?

Thanks

May 16, 2008 3:31 AM
 

Philippe Sentenac [MVP SharePoint] said:

Après vous avoir parlé de ce que l'on pouvait faire avec les extensions de méthodes et un peu de réflection,

May 20, 2008 4:03 AM
 

Shared Points for SharePoint... said:

Stefan Gossner has published a great article on the subject: In an earlier article I have discussed that

May 28, 2008 1:58 AM
 

sergioko said:

Does MS have a plan to close any of this leaks like in BreakRoleInheritance() internally? What happens to our perfect existing code, if next  MOSS/WSS service pack will invent a proper dispose of ParentWeb in there? Double disposal?

May 29, 2008 4:07 AM
 

Mario Cortés Flores said:

Puesta en situación En uno de nuestros proyectos hemos tenido que manejar el contexto del usuario en

June 3, 2008 6:00 PM
 

First Hand said:

Источник...Смысл в том, чтобы уничтожать объекты SPweb, SPSite и т.п. методом Dispose() принудительно....

June 17, 2008 8:41 AM
 

ajayrsawant said:

We have code where at times we'll be returning an SPWeb object from a function. So for example:

public SPWeb getDeptWeb()

{

SPWeb deptWeb = SpSite.OpenWeb(SpContext.Web.ID);

...

return deptWeb;

}

How can we dispose of the SPWeb object in this instance? Or is it sufficient to dispose it where we're accepting the returned parameter?

June 22, 2008 4:22 AM
 

Meine SharePoint-Notizen said:

Beim Programmieren im SharePoint-Umfeld sollte man großen Wert auf saubere und sicherer Programmierung

July 10, 2008 6:45 AM
Anonymous comments are disabled

© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker