将linq与Sharepoint一起使用并处理对象

时间:2009-03-18 05:43:50

标签: linq sharepoint

如何在以下查询中处理对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?

编辑:

在这种情况下调用垃圾收集是一个好主意吗?

2 个答案:

答案 0 :(得分:6)

不幸的是,你做到了。 麻烦从SPSite.AllWebs属性开始。 SPWeb.Web属性也不安全。

阅读this very thorough reference您需要担心处置SharePoint对象的情况。

(我建议将此添加到您的SharePoint备忘单中)。

因此,我觉得当前的SharePoint对象模型无法安全地与LINQ语法一起使用。

您的代码需要重新编写,并且各种隐含的循环都已分解,以便您可以明确地处理所涉及的对象。

修改 SPDisposeCheck工具是一个命令行控制台应用程序,它将扫描您的.NET程序集并根据上述最佳实践指南警告您未处理的引用。看看吧。

http://code.msdn.microsoft.com/SPDisposeCheck

http://blogs.msdn.com/sharepoint/archive/2008/11/12/announcing-spdisposecheck-tool-for-sharepoint-developers.aspx

答案 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等)是不安全的。另外swusing块之外使用是不安全的,因为迭代器的SPWebCollections将与现在处置的SPSite绑定。

那就是说,像这样列举所有网络的代码(两次!)是非常昂贵的。如果只使用spSite.AllWebs[path]代替您的from / where,几乎可以肯定这是一种更有效的方法。

关于垃圾收集,由于分配了GC甚至不知道的非托管内存,因此需要处理这些对象。

最后,请注意您的“GetElevatedSite”实用程序。如果您在帮助程序方法中使用RunWithElevatedPrivileges来获取提升的SPSite,则可能会因为SPSite退出该提升的上下文而遇到许多问题。如果可能,我建议使用SPSite模拟 - 我首选的方法是here