Dispose should not be called on this object. // SPDisposeCheck comment
-
07-10-2020 - |
题
In the code below, within using
directive, for rootweb
, Dispose();
method will be called implicitly, is that correct? Or should I need a using
directive for this: SPWeb rootweb = site.RootWeb
since I am not using new
keyword?
The reason I am asking because SPDisposeCheck
gives following comments:
Dispose should not be called on this object.
Initial Assignment: rootweb := site.
{Microsoft.SharePoint.SPSite}get_RootWeb()
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
var site = properties.Feature.Parent as SPSite;
if (site != null)
{
AddTaxonomyField(site);
}
}
private void AddTaxonomyField(SPSite site)
{
SPContextManager.Current.LogManager.LogInformationToDevelopers(String.Format("Adding {0} to {1}.", CorCatColumn, site.Url));
try
{
using (SPWeb rootweb = site.RootWeb) // At this line
{
if (!rootweb.Fields.ContainsField(CorCatColumn))
{
TaxonomySession session = new TaxonomySession(site);
TermStore ts = session.DefaultSiteCollectionTermStore;
if (session.TermStores.Count != 0)
{
string taxonomyField = "SomeField";
string noteField = "SomeField";
rootweb.Fields.AddFieldAsXml(noteField);
rootweb.Update();
rootweb.Fields.AddFieldAsXml(taxonomyField);
rootweb.Update();
}
}
}
}
catch (Exception ex)
{
SPContextManager.Current.LogManager.LogErrorToDevelopers(ex);
}
}
解决方案
Do not explicitly (or via using) call Dispose()
on the SPSite.RootWeb
property. The dispose cleanup will be handled automatically by the SharePoint and the .NET framework.
For existing SharePoint customizations removal of explicit RootWeb Dispose is recommended to avoid an edge case condition where the SPContext.Current.Web
has equality to the SPSite.RootWeb
.
Problems can occur when disposing RootWeb
when obtained from any variation of SPContext
(e.g., SPContext.Site.RootWeb
, SPContext.Current.Site.RootWeb
and GetContextSite(Context).RootWeb
). Note the owning SPSite
object must be properly disposed (or not disposed in the case of SPContext
).
So in you case, just do like this:
private void AddTaxonomyField(SPSite site)
{
SPContextManager.Current.LogManager.LogInformationToDevelopers(String.Format("Adding {0} to {1}.", CorCatColumn, site.Url));
try
{
SPWeb rootweb = site.RootWeb
//...
But make sure you dispose the SPSite
you pass into the AddTaxonomyField
in the function that calls AddTaxonomyField
UNLESS you take it from SPContext
. As you get it from properties.Feature.Parent
, you should not Dispose it, so I'd just do the above mentioned change.
其他提示
The code is wrong. You need to use using
directive only with objects that you created yourself. The code would be correct in this case:
private void AddTaxonomyField(SPSite site)
{
using (SPWeb web = site.OpenWeb()) //need "using" because you opened the SPWeb yourself
{
}
}
This code would dispose of the web object at the end of using statement. This would be correct as well:
private void AddTaxonomyField(SPSite site)
{
var rootWeb = site.RootWeb; // no need for "using" since the object is managed by SPSite.
}
In your example, you haven't opened a new web but instead you used SPSite.RootWeb
object (and SPSite
will take care of that for you). Since the SPSite.RootWeb
wasn't opened (or created in simple terms) by you - therefor there is no need to use using
or call .Dispose()
.
I believe this is your third similar question in a row :) Just note the following guidelines and it might help:
- using = automatic dispose;
- You don't dispose of something you don't own (create);