惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
H
Help Net Security
F
Fortinet All Blogs
MyScale Blog
MyScale Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 司徒正美
量子位
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
小众软件
小众软件
Recorded Future
Recorded Future
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
I
InfoQ
Microsoft Security Blog
Microsoft Security Blog
Scott Helme
Scott Helme
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
IT之家
IT之家
AI
AI
WordPress大学
WordPress大学
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
U
Unit 42
V2EX - 技术
V2EX - 技术
MongoDB | Blog
MongoDB | Blog
Schneier on Security
Schneier on Security
博客园 - Franky
H
Heimdal Security Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Jina AI
Jina AI
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
N
News | PayPal Newsroom
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
I
Intezer
Hacker News - Newest:
Hacker News - Newest: "LLM"
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园_首页
罗磊的独立博客
H
Hackread – Cybersecurity News, Data Breaches, AI and More
雷峰网
雷峰网

博客园 - 赏梅斋

直接访问K2数据库找未归档正在进行中的流程的SQL语句 SharePoint学习笔记1--Asp.net与SharePoint的Session机制 安装Lync Server前端必备组件Wmf2008R2时失败的问题 域环境安装SQLServer时出现“帐户名与安全标识之间无任何映射”的问题 网络发现不能启用的问题 sharepoint 2010 与sqlserver denali的支持性安装测试 SPES2011开始注册了! K2 Blackpearl 4.5 怎样配置SQLUM SharePoint2010企业开发最佳实践(九)---- 事件接收器的最佳做法 SharePoint2010企业开发最佳实践(八)---- SPWeb 对象 SharePoint2010企业开发最佳实践(六)---- 用于确保释放对象的编码技术 SharePoint2010企业开发最佳实践(五)---- 查找错误释放的对象 SharePoint2010企业开发最佳实践(四)---- 关于使用可释放的 SharePoint 对象的介绍 SharePoint2010企业开发最佳实践(三)---- 对象缓存技术 SharePoint2010企业开发最佳实践(二)---- 处理大型文件夹和列表 SharePoint2010企业开发最佳实践(一)----在 SharePoint Server 中编写有效代码 修改MOSS服务器名称 赏梅斋最新推出论坛Microsoft Information Worker 2008年3月19日主题讨论日
SharePoint2010企业开发最佳实践(七)---- SPSite 对象
赏梅斋 · 2011-02-11 · via 博客园 - 赏梅斋

通常,调用应用程序无论何时使用新 SPSite 构造函数(任何签名),都应该在用完对象之后调用 Dispose() 方法。如果 SPSite 对象是从 GetContextSite() 中获得的,则该调用应用程序 应该释放对象。因为 SPWebSPSite 对象会保留通过此方式派生的内部列表,所以释放对象可能会导致 SharePoint 对象模型行为无法预料。SharePoint Foundation 在页面完成之后会在内部枚举此列表以正确释放对象。

SPSiteCollection 类

SPSiteCollection.Add 方法

SPSiteCollection.Add 方法将创建并返回新的 SPSite 对象。应该释放从 SPSiteCollection.Add 方法中返回的任何 SPSite 对象。

不良的编码实践

void SPSiteCollectionAddLeak()
{
    SPWebApplication webApp = new SPSite("http://www.msiw.net/;
    SPSiteCollection siteCollections = webApp.Sites;
    SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User",
      "spirit@msiw.net");
    // SPSite siteCollection leak.
}

良好的编码实践

void SPSiteCollectionAddNoLeak()
{
    SPWebApplication webApp = new SPSite("http://www.msiw.net/;
    SPSiteCollection siteCollections = webApp.Sites;
    using (SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User",
      "spirit@msiw.net"))
    {
    } // SPSite object siteCollection.Dispose() automatically called.
}

SPSiteCollection [ ] 索引运算符

SPSiteCollection [] 索引运算符会针对每次访问返回一个新的 SPSite 对象。将会创建 SPSite 实例,即使已经访问了该对象也不例外。以下代码示例演示了 SPSite 对象的不正确释放过程。

不良的编码实践 #1

void SPSiteCollectionIndexerLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        SPSite siteCollectionInner = siteCollections[0];
        // SPSite siteCollectionInner leak.
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}

void SPSiteCollectionForEachLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        foreach (SPSite siteCollectionInner in siteCollections)
        {
            // SPSite siteCollectionInner leak.
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}

void SPSiteCollectionIndexerNoLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/"))
    {
        SPSite siteCollectionInner = null;
        try
        {
            SPWebApplication webApp = siteCollectionOuter.WebApplication;
            SPSiteCollection siteCollections = webApp.Sites;

            siteCollectionInner = siteCollections[0];
        }
        finally
        {
            if (siteCollectionInner != null)
                siteCollectionInner.Dispose();
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}

void SPSiteCollectionForEachNoLeak()
{
    using (SPSite siteCollectionOuter = new SPSite("http://www.msiw.net/”))
    {
        SPWebApplication webApp = siteCollectionOuter.WebApplication;
        SPSiteCollection siteCollections = webApp.Sites;

        foreach (SPSite siteCollectionInner in siteCollections)
        {
            try
            {
                // ...
            }
            finally
            {
                if(siteCollectionInner != null)
                    siteCollectionInner.Dispose();
            }
        }
    } // SPSite object siteCollectionOuter.Dispose() automatically called.
}

SPSite.AllWebs 属性 (SPWebCollection)

SPSite.AllWebs.Add 方法

SPSite.AllWebs.Add 方法将创建并返回 SPWeb 对象。应该释放从 SPSite.AllWebs.Add 中返回的任何 SPWeb 对象。

不良的编码实践

void AllWebsAddLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        SPWeb web = siteCollection.AllWebs.Add("site-relative URL");
        // SPWeb object leaked.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

良好的编码实践

void AllWebsAddNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

SPWebCollection.Add 方法

SPWebCollection.Add 方法将创建并返回需要释放的 SPWeb 对象。

不良的编码实践

void SPWebCollectionAddLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
            SPWeb innerWeb = webCollection.Add(strWebUrl);  // Must dispose innerWeb.
            // innerWeb leak.
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

良好的编码实践

void SPWebCollectionAddNoLeak(string strWebUrl)
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            SPWebCollection webCollection = siteCollection.AllWebs; // No AllWebs leak just getting reference.
            using (SPWeb innerWeb = webCollection.Add(strWebUrl))
            {
                //...
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

SPSite.AllWebs [ ] 索引运算符

SPSite.AllWebs [] 索引运算符会在每次访问对象后返回一个新的 SPWeb 实例。索引操作过程中将会创建对象,即使已经访问了该对象也不例外。如果未正确关闭,则以下代码示例会将 SPWeb 对象保留在 .NET Framework 垃圾收集器中。

不良的编码实践

void AllWebsForEachLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                // Explicitly dispose here to avoid out of memory leaks with large number of SPWeb objects.
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

void AllWebsForEachNoLeakOrMemoryOOM()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in siteCollection.AllWebs)
            {
                try
                {
                    // ...
                }
                finally
                {
                    if(innerWeb != null)
                        innerWeb.Dispose();
                }
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

void AllWebsIndexerNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb web = siteCollection.AllWebs[0])
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

SPSite.OpenWeb 和 SPSite. SelfServiceCreateSite 方法

SPSite 对象的 OpenWeb() 方法和 SelfServiceCreateSite 方法(所有签名)将创建 SPWeb 对象并将其返回给调用方。此新对象未存储在 SPSite 对象中,并且未在 SPSite 类中的任何地方被释放。因此,应该释放通过这些方法创建的任何对象。

不良的编码实践

void OpenWebLeak()
{
    using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
    {
        // SPSite leaked !
    } // SPWeb object web.Dispose() automatically called.
}

良好的编码实践

void OpenWebNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        using (SPWeb web = siteCollection.OpenWeb())
        {
        } // SPWeb object web.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called.
}

SPSite.RootWeb 属性

前面的指导指明了调用应用程序释放 SPSite.RootWeb 属性应该发生在即将释放使用该属性的 SPSite 对象之前。这不再是正式的指导。释放清理是由 SharePoint Foundation 和 SharePoint Server 自动处理的。此外,SPSite 属性 LockIssueOwnerSecondaryContact 在内部使用了 RootWeb 属性。按照 RootWeb 的更新的指导,每当使用其中的任意属性时对 SPSite.RootWeb 属性调用 Dispose 方法不再是可取的。

良好的编码实践

public void RootWebBestPractice()
{
    // New SPSite.
    using (SPSite siteCollection = new SPSite("http://www.msiw.net/"))
    {
        SPWeb rootWeb1 = siteCollection.RootWeb;
        // No explicit rootWeb1 dispose required.
    }  // siteCollection automatically disposed by implementing using().
    // rootWeb1 will be Disposed by SPSite.

    // SPContext and SPControl
    SPWeb rootWeb2 = SPContext.Current.Site.RootWeb;
    // Also would apply to SPControl.GetContextSite(Context);
    // No explicit rootWeb2 dispose required because it is obtained from SPContext.Current.Site.
}