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应该不被处置,如果是的话确实会引起问题。
答案 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部件执行操作。
SPSecurity.CodeToRunElevated
考虑到这些,我最终会写这个。 。 。现在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中获得。