使用已处置的 SPSite 和 SPWeb 对象
我很高兴继承了一个写得很糟糕的 SharePoint 项目。
显然,最初的开发人员是可重用代码的忠实粉丝(30% 的代码在不使用任何库的情况下在 20 个项目中重用 - 你猜怎么着?)。
我经常发现他的代码调用一些 Common.OpenWeb
方法来检索 SPWeb
对象来操作 SharePoint 内容。这个函数的大多数化身看起来都一模一样:
public SPWeb OpenWeb()
{
String strSiteUrl = ConfigurationManager.AppSettings["SiteUrl"].ToString();
SPSite site = null;
SPWeb web = null;
try
{
using (site = new SPSite(strSiteUrl))
{
using (web = site.OpenWeb())
{
return web;
}
}
}
catch (Exception ex)
{
LogEvent("Error occured in OpenWeb : " + ex.Message, EventLogEntryType.Error);
}
return web;
}
现在我真的很担心。
这如何在生产中发挥作用?这个方法总是返回一个已处理的对象,对吧?
它究竟有多不稳定?
更新:
此方法按以下方式使用:
oWeb = objCommon.OpenWeb();
SPList list = oWeb.Lists["List name"];
SPListItem itemToAdd = list.Items.Add();
itemToAdd["Some field"] = "Some value";
oWeb.AllowUnsafeUpdates = true;
itemToAdd.Update();
oWeb.AllowUnsafeUpdates = false;
为了简洁起见,我省略了吞咽try-catch
。
此代码将值插入列表!这是一个写入操作,我很确定 Request
属性正在用于此操作。那么如何才能发挥作用呢?
I was happy enough to have inherited a terribly written SharePoint project.
Apparently, the original developer was a big fan of reusable code (30% of code is reused across 20 projects without using any libraries—guess how?).
I would often find his code calling some Common.OpenWeb
method to retrieve SPWeb
object for operating SharePoint stuff. Most of this function's incarnations look exactly the same:
public SPWeb OpenWeb()
{
String strSiteUrl = ConfigurationManager.AppSettings["SiteUrl"].ToString();
SPSite site = null;
SPWeb web = null;
try
{
using (site = new SPSite(strSiteUrl))
{
using (web = site.OpenWeb())
{
return web;
}
}
}
catch (Exception ex)
{
LogEvent("Error occured in OpenWeb : " + ex.Message, EventLogEntryType.Error);
}
return web;
}
And now I'm really worried.
How come this works in production? This method always returns a disposed object, right?
How unstable is it, exactly?
UPDATE:
This method is used in the following fashion:
oWeb = objCommon.OpenWeb();
SPList list = oWeb.Lists["List name"];
SPListItem itemToAdd = list.Items.Add();
itemToAdd["Some field"] = "Some value";
oWeb.AllowUnsafeUpdates = true;
itemToAdd.Update();
oWeb.AllowUnsafeUpdates = false;
I omitted the swallowing try-catch
for brevity.
This code inserts value into the list! This is a write operation, I'm pretty sure Request
property is being used for this. Then how can it work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,简短的回答:该方法确实返回一个已处理的对象。对象在被处置后不应再使用,因为它不再处于可靠状态,并且对该对象执行的任何进一步操作都应该(理论上)抛出 ObjectDisposeException。
现在,经过一番挖掘后,SharePoint 对象似乎并不遵循该规则。
SPWeb
在被处置后不仅不会抛出ObjectDisposeException
,而且实际上在其Request
属性中测试这种情况如果已被释放,则从其内部状态重建有效的SPRequest
。看来至少
SPWeb
的设计是即使在废弃状态下也能完全发挥作用。为什么,我不知道。也许它是为了容纳像您正在处理的那样的客户端代码。也许这是某种我无法理解的复杂优化。也就是说,我建议您不要依赖这种行为,因为它将来可能会发生变化(尽管考虑到 Microsoft 关于 bug-for-bug 向后兼容性的政策,它可能不会) 。
当然,您仍然会泄漏新的
SPRequest
实例,这可能会造成相当大的成本。永远、永远不要使用已处置的对象,即使 SharePoint 允许您逃脱惩罚。First, the short answer: that method indeed returns a disposed object. An object should not be used after being disposed, because it's no longer in a reliable state, and any further operation performed on that object should (theoretically) throw an ObjectDisposedException.
Now, after digging a little, SharePoint objects don't seem to follow that rule. Not only does
SPWeb
never throwObjectDisposedException
after being disposed, but it actually tests for that case in itsRequest
property and rebuilds a validSPRequest
from its internal state if it has been disposed.It seems that at least
SPWeb
was designed to be fully functional even in a disposed state. Why, I don't know. Maybe it's for accommodating client code like the one you're working on. Maybe it's some kind of complicated optimization I can't possibly understand.That said, I'd suggest you don't rely on that behavior, because it might change in the future (even though, given Microsoft's policy on bug-for-bug backwards compatibility, it might not).
And of course, you will still leak the new
SPRequest
instance, which can be quite costly. Never, ever, use a disposed object, even if SharePoint lets you get away with it.