通常,调用应用程序无论何时使用新 SPSite 构造函数(任何签名),都应该在用完对象之后调用 Dispose() 方法。如果 SPSite 对象是从 GetContextSite() 中获得的,则该调用应用程序不 应该释放对象。因为 SPWeb 和 SPSite 对象会保留通过此方式派生的内部列表,所以释放对象可能会导致 SharePoint 对象模型行为无法预料。SharePoint Foundation 在页面完成之后会在内部枚举此列表以正确释放对象。
SPSiteCollection 类
SPSiteCollection.Add 方法
SPSiteCollection.Add 方法将创建并返回新的 SPSite 对象。应该释放从 SPSiteCollection.Add 方法中返回的任何 SPSite 对象。
不良的编码实践
void SPSiteCollectionAddLeak(){
SPWebApplication webApp = new SPSite("http://www.msiw.net/;
SPSiteCollection siteCollections = webApp.Sites;
SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User",
"spirit@msiw.net");
// SPSite siteCollection leak.
}
良好的编码实践
{
SPWebApplication webApp = new SPSite("http://www.msiw.net/;
SPSiteCollection siteCollections = webApp.Sites;
using (SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User",
"spirit@msiw.net"))
{
} // SPSite object siteCollection.Dispose() automatically called.
}
SPSiteCollection [ ] 索引运算符
SPSiteCollection [] 索引运算符会针对每次访问返回一个新的 SPSite 对象。将会创建 SPSite 实例,即使已经访问了该对象也不例外。以下代码示例演示了 SPSite 对象的不正确释放过程。
不良的编码实践 #1
void SPSiteCollectionIndexerLeak()
{
using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
{
SPWebApplication webApp = siteCollectionOuter.WebApplication;
SPSiteCollection siteCollections = webApp.Sites;
SPSite siteCollectionInner = siteCollections[0];
// SPSite siteCollectionInner leak.
} // SPSite object siteCollectionOuter.Dispose() automatically called.
}
不良的编码实践 #2
使用 foreach 循环
void SPSiteCollectionForEachLeak()
{
using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
{
SPWebApplication webApp = siteCollectionOuter.WebApplication;
SPSiteCollection siteCollections = webApp.Sites;
foreach (SPSite siteCollectionInner in siteCollections)
{
// SPSite siteCollectionInner leak.
}
} // SPSite object siteCollectionOuter.Dispose() automatically called.
}
良好的编码实践 #1
使用索引运算符
void SPSiteCollectionIndexerNoLeak()
{
using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
{
SPSite siteCollectionInner = null;
try
{
SPWebApplication webApp = siteCollectionOuter.WebApplication;
SPSiteCollection siteCollections = webApp.Sites;
siteCollectionInner = siteCollections[0];
}
finally
{
if (siteCollectionInner != null)
siteCollectionInner.Dispose();
}
} // SPSite object siteCollectionOuter.Dispose() automatically called.
}
良好的编码实践 #2
使用 foreach 循环
void SPSiteCollectionForEachNoLeak()
{
using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/”))
{
SPWebApplication webApp = siteCollectionOuter.WebApplication;
SPSiteCollection siteCollections = webApp.Sites;
foreach (SPSite siteCollectionInner in siteCollections)
{
try
{
// ...
}
finally
{
if(siteCollectionInner != null)
siteCollectionInner.Dispose();
}
}
} // SPSite object siteCollectionOuter.Dispose() automatically called.
}
SPSite.AllWebs 属性 (SPWebCollection)
SPSite.AllWebs.Add 方法
SPSite.AllWebs.Add 方法将创建并返回 SPWeb 对象。应该释放从 SPSite.AllWebs.Add 中返回的任何 SPWeb 对象。
不良的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
SPWeb web = siteCollection.AllWebs.Add("site-relative URL");
// SPWeb object leaked.
} // SPSite object siteCollection.Dispose() automatically called.
}
良好的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
{
} // SPWeb object web.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
SPWebCollection.Add 方法
SPWebCollection.Add 方法将创建并返回需要释放的 SPWeb 对象。
不良的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
SPWeb innerWeb = webCollection.Add(strWebUrl); // Must dispose innerWeb.
// innerWeb leak.
} // SPWeb object outerWeb.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
良好的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
using (SPWeb innerWeb = webCollection.Add(strWebUrl))
{
//...
}
} // SPWeb object outerWeb.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
SPSite.AllWebs [ ] 索引运算符
SPSite.AllWebs [] 索引运算符会在每次访问对象后返回一个新的 SPWeb 实例。索引操作过程中将会创建对象,即使已经访问了该对象也不例外。如果未正确关闭,则以下代码示例会将 SPWeb 对象保留在 .NET Framework 垃圾收集器中。
不良的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
foreach (SPWeb innerWeb in siteCollection.AllWebs)
{
// Explicitly dispose here to avoid out of memory leaks with large number of SPWeb objects.
}
} // SPWeb object outerWeb.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
良好的编码实践 #1
使用 foreach 循环
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb outerWeb = siteCollection.OpenWeb())
{
foreach (SPWeb innerWeb in siteCollection.AllWebs)
{
try
{
// ...
}
finally
{
if(innerWeb != null)
innerWeb.Dispose();
}
}
} // SPWeb object outerWeb.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
良好的编码实践 #2
使用索引运算符
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb web = siteCollection.AllWebs[0])
{
} // SPWeb object web.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
SPSite.OpenWeb 和 SPSite. SelfServiceCreateSite 方法
SPSite 对象的 OpenWeb() 方法和 SelfServiceCreateSite 方法(所有签名)将创建 SPWeb 对象并将其返回给调用方。此新对象未存储在 SPSite 对象中,并且未在 SPSite 类中的任何地方被释放。因此,应该释放通过这些方法创建的任何对象。
不良的编码实践
{
using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
{
// SPSite leaked !
} // SPWeb object web.Dispose() automatically called.
}
良好的编码实践
{
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
using (SPWeb web = siteCollection.OpenWeb())
{
} // SPWeb object web.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
SPSite.RootWeb 属性
前面的指导指明了调用应用程序释放 SPSite.RootWeb 属性应该发生在即将释放使用该属性的 SPSite 对象之前。这不再是正式的指导。释放清理是由 SharePoint Foundation 和 SharePoint Server 自动处理的。此外,SPSite 属性 LockIssue、Owner 和 SecondaryContact 在内部使用了 RootWeb 属性。按照 RootWeb 的更新的指导,每当使用其中的任意属性时对 SPSite.RootWeb 属性调用 Dispose 方法不再是可取的。
良好的编码实践
public void RootWebBestPractice()
{
// New SPSite.
using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
{
SPWeb rootWeb1 = siteCollection.RootWeb;
// No explicit rootWeb1 dispose required.
} // siteCollection automatically disposed by implementing using().
// rootWeb1 will be Disposed by SPSite.
// SPContext and SPControl
SPWeb rootWeb2 = SPContext.Current.Site.RootWeb;
// Also would apply to SPControl.GetContextSite(Context);
// No explicit rootWeb2 dispose required because it is obtained from SPContext.Current.Site.
}