如何在以下查询中处理对subWeb的引用?
using (SPSite spSite = Utility.GetElevatedSite(_rootUrl))
{
from SPWeb web in spSite.AllWebs
where web.ServerRelativeUrl.ToLower() == path
from SPWeb subWeb in web.Webs
select subWeb
}
如果iam已经在使用语句中包含了spSite,我是否还需要担心处理subWeb?
编辑:
在这种情况下调用垃圾收集是一个好主意吗?
答案 0 :(得分:6)
不幸的是,你做到了。 麻烦从SPSite.AllWebs属性开始。 SPWeb.Web属性也不安全。
阅读this very thorough reference您需要担心处置SharePoint对象的情况。
(我建议将此添加到您的SharePoint备忘单中)。
因此,我觉得当前的SharePoint对象模型无法安全地与LINQ语法一起使用。
您的代码需要重新编写,并且各种隐含的循环都已分解,以便您可以明确地处理所涉及的对象。
修改强> SPDisposeCheck工具是一个命令行控制台应用程序,它将扫描您的.NET程序集并根据上述最佳实践指南警告您未处理的引用。看看吧。
答案 1 :(得分:2)
原始问题的技术答案是合格的“否”:SPWeb
处置时,SPSite
打开的所有SPSite
个对象都会自动处理。但是,在实践中,最好在完成后尽快处置SPWeb
以减少内存压力,尤其是在处理打开多个SPWeb
对象的代码时。 p>
在C#中实现LINQ的这种部署安全行为实际上非常简单。您可以在this post中找到完整的详细信息,但简短的版本是C#迭代器可以为您处理。使用我的AsSafeEnumerable()
扩展方法,您的代码相对安全,如下所示:
using (SPSite spSite = Utility.GetElevatedSite(_rootUrl))
{
var sw = from SPWeb web in spSite.AllWebs.AsSafeEnumerable()
where web.ServerRelativeUrl.ToLower() == path
from SPWeb subWeb in web.Webs.AsSafeEnumerable()
select subWeb;
foreach(SPWeb aSubWeb in sw)
{
// Do something
}
}
现在,我已分配给sw
的查询结果是IEnumerable<SPWeb>
类型的惰性迭代器。当您枚举该结果时,每个SPWeb
将在枚举器移动到下一个项目时被处理。这意味着在SPWeb
循环之外使用SPList
引用或从其创建的任何SP *对象(foreach
等)是不安全的。另外sw
在using
块之外使用是不安全的,因为迭代器的SPWebCollections
将与现在处置的SPSite
绑定。
那就是说,像这样列举所有网络的代码(两次!)是非常昂贵的。如果只使用spSite.AllWebs[path]
代替您的from
/ where
,几乎可以肯定这是一种更有效的方法。
关于垃圾收集,由于分配了GC甚至不知道的非托管内存,因此需要处理这些对象。
最后,请注意您的“GetElevatedSite”实用程序。如果您在帮助程序方法中使用RunWithElevatedPrivileges
来获取提升的SPSite
,则可能会因为SPSite
退出该提升的上下文而遇到许多问题。如果可能,我建议使用SPSite
模拟 - 我首选的方法是here。