I've been using the following code in a .NET 1.1 SharePoint 2003 environment and it 开发者_运维问答works great:
try
{
site = SPControl.GetContextSite(Context);
web = site.OpenWeb();
...
}
catch (Exception export)
{
output.Write("Caught Exception: <br/><br/>");
output.Write(export.Message + "<br><br>");
output.Write(export.StackTrace);
}
finally
{
if (web != null)
web.Dispose();
if (site != null)
site.Dispose();
}
However, I'm currently porting the code to a .NET 2.0 SharePoint 2007 environment and I get the following error message:
"Trying to use an SPWeb object that has been closed or disposed and is no longer valid."
If I comment out the Dispose() code, it works fine. But won't this cause memory leaks? What's the best way to fix the problem?
When you get the SPSite object from GetContextSite you are getting an object that is shared with everything else running on that page.
After you Dispose of it other code is trying to use it - hence the error.
You should only Dispose objects that you create yourself and not ones that you get with GetContextSite.
The quick fix is (as Iambriansreed says) is to remove the finally block and replace the first two lines with.
SPSite site = SPContext.Current.Site; // Do you even need this?
SPweb web = SPContext.Current.Web;
Better performance and no memory leak as the SharePoint framework handles both creating and disposing of objects retrieved through SPContext.
However - its a complex and poorly understood subject so a thorough read through of the Best Practices: Using Disposable Windows SharePoint Services Objects and using the SPDisposeCheck tool is essential.
When handling disposable object, and SharePoint in particular, it is simpler to use using
:
using(SPSite site = new SPSite("..."))
using(SPWeb web = site.OpenWeb("..."))
{
}
However, note that you should not dispose of elements that come from current context - they are shared, and disposing of them may cause this error. This is a common mistake, and in my opinion should have been handled better by the API.
See also - Using Disposable Windows SharePoint Services Objects:
SPContext objects are managed by the SharePoint framework and should not be explicitly disposed in your code. This is true also for the SPSite and SPWeb objects returned by SPContext.Site, SPContext.Current.Site, SPContext.Web, and SPContext.Current.Web.
Also a better way to do the above:
site = SPControl.GetContextSite(Context);
web = site.OpenWeb()
is the following:
SPSite site = SPContext.Current.Site;
SPweb web = SPContext.Current.Web;
No memory leaks here. Seriously though; going to 2007 not 2010?
Put your code in using statements which will auto call dispose when the objects go out of scope.e.g.
using(site = SPControl.GetContextSite(Context))
{
using(web = site.OpenWeb())
{
//your code
}
}
精彩评论