SPWeb.Site,你应该调用Dispose()吗?

时间:2009-08-06 09:25:50

标签: sharepoint dispose

2009年8月6日更新15:52 简短回答原始问题:

我找不到有关处理 SPWeb.Site 的任何参考资料。我已经阅读了一些关于处理SharePoint对象的更流行的最佳实践文档:

不幸的是,这些指南都没有提到SPWeb.Site。为了给出一些上下文,我正在编写一个公共扩展API,它接受SPWeb作为方法的参数,即:。

public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)
{
     ......

     SPSite site = web.Site;
     ......

     **OR** ??

     using (SPSite site = web.Site)
     {
         ....
     }
}

我在SPWeb的refelector中看起来像是Close()方法,它由SPWeb.Dispose()调用,并且没有任何内容表明实际的SPSite成员字段已被处理掉。

更新:06/08/2009 13:47

Alex's建议

“将它放在一个运行100次的循环中,并使用WSS v3和MOSS 2007中的SPSite / SPWeb泄漏故障排除中描述的SPRequestStackTrace注册表项来检查您的测试代码是否是问题的根源。”

我在webpart中运行了以下代码:

 for (int i = 0; i < 100; i++)
 {
     using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
     {
            SPSite site = web.Site;
            Debug.WriteLine(site.Url);
     }
 }

SharePoint日志中没有任何内容。

虽然我会毫不犹豫地从这个天真的实验中得出任何真正的结论,但这表明处理SPWeb.Site需要。如果有人对这个问题有了更多的了解,那真是太好了。

更新:06/08/2009 14:52 在Greg的评论提示下,我编写了m_Site的赋值,看起来它最终总是通过内部构造函数传递给SPWeb。例如。 SPWeb.OpenWeb将 this 传递给新的SPWeb()。所以我更确定SPWeb.Site应该被处置,如果是的话确实会引起问题。

8 个答案:

答案 0 :(得分:8)

Kirk's answer是正确的。在创建SPWeb之前,您必须拥有一些SPSite句柄,这与调用SPWeb.Site时的SPSite实例相同。

让我们仔细考虑一下它的含义 - 如果你不控制SPSite的创建,但是它的一个子网是从外部代码传递给你的,并且当你将控制权返回给调用代码时你就处理了这个网站,你已经处置了一个他们可能没有完成的网站!把自己放在调用代码中:将SPWeb传递给方法,当该方法完成后,您使用的SPSite已经关闭。清理他们分配的资源始终是实施者的责任。在这种情况下,请勿丢弃SPSite。

答案 1 :(得分:5)

只是想到我的头脑(有时是危险的)......

如果没有SPSite,您似乎无法拥有SPWeb。所以,如果你没有通过SPSite获得SPWeb(通过新的SPSite或提供给你的那个),那么你可能不必担心处置SPSite。

但这只是猜想。好问题!

答案 2 :(得分:2)

目前尚不清楚。有Stefan's blog表示“您需要确保只处理代码所拥有的SPSite和SPWeb对象”。然后来自Michael Washam(微软)的this thread指出这种模式确实泄漏了。

除非您可以找到其他参考或其他人知道,为什么不在开发服务器中测试它并将结果添加为此问题的答案?将它放在一个运行100次的循环中,并使用Troubleshooting SPSite/SPWeb leaks in WSS v3 and MOSS 2007中描述的SPRequestStackTrace注册表项来检查您的测试代码是否是问题的根源。

答案 3 :(得分:2)

Reflector告诉我们,当您调用Site属性时,这是在SPWeb对象内运行的代码:

public SPSite Site
{
    get
    {
        return this.m_Site;
    }
}

它不会创建一个新的SPSite对象,只返回它已经拥有的对象,如果需要,可以由SPWeb.Dispose()来处理。所以,你可以安全地使用它,我会避免处理它,以免SPWeb依赖性对你来说都很糟糕。

答案 4 :(得分:1)

您是否尝试使用SPDisposeCheck检查程序集?也许它会为您提供如何处理问题的提示。

答案 5 :(得分:1)

我经常在我的SharePoint代码中使用此模式作为经验法则,如果调用depose不会导致我称之为崩溃的任何内容。我遵循的另一条规则是我尽量不创建不会导致SPRequest对象净增益的扩展(SPRequest对象是与所有重量级com进行对话的.net对象objcets)

现在打破你的榜样

 for (int i = 0; i < 100; i++)
 {
     using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
     {
            SPSite site = web.Site;
            Debug.WriteLine(site.Url);
     }
 }

这里的关键是SPContext.Current.Site SPContext将自我正确清理(少数几个对象之一),因为我们知道网站已正确清理我希望网站得到了清理,但这远不是你问题的正确答案。 (请注意,您应该泄漏通过OpenWeb获得的网站)

public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)

您需要让SPSite对Web部件执行操作。

  1. web.Site属性实际上会在网络被丢弃之后自行清理。
  2. 为什么不直接传入SPSite对象并让函数用户担心呢? 在大多数情况下,我认为他们无论如何都会使用SPContext.Current.Site进行调用。
  3. 大多数时候我不得不担心权限,而不是我们的dll中的每个人最终都会加入GAC,因此当我编写新的扩展方法时,我最终必须将其包装为SPSecurity.CodeToRunElevated
  4. 考虑到这些,我最终会写这个。 。 。现在Dispose检查将在这种情况下发生,因为SPSite作为参数传入,因为它无法跟踪它所处理的范围。

    public static void GetWebPartFromCatalog(this SPSite site, string webPartName) {
         SPSecurity.CodeToRunElevated( () => {
             using(SPSite suSite = new SPSite(site.Id)){
                 //do what you need to do
             }
         };
    }
    

答案 6 :(得分:1)

Stefan Gobner有一篇很好的文章: 的 Troubleshooting SPSite/SPWeb leaks in WSS v3 and MOSS 2007

...请务必在代码库中使用 SPDispose check tool

答案 7 :(得分:0)

如果是新对象,则需要删除SPSite / SPWeb实例

例如

using(SPSite site = new SPSite("url"))
{
    DoSomething;
}

这里使用将负责删除对象 但是,如果您从SPContext.Current获得对象的引用,则不应显式处置该对象,因为该引用应该可以从SPContext.Current中获得。