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

推荐订阅源

美团技术团队
D
DataBreaches.Net
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
Check Point Blog
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
IT之家
IT之家
月光博客
月光博客
U
Unit 42
K
Kaspersky official blog
T
Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
GbyAI
GbyAI
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
云风的 BLOG
云风的 BLOG
酷 壳 – CoolShell
酷 壳 – CoolShell
I
InfoQ
Engineering at Meta
Engineering at Meta
Recorded Future
Recorded Future
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Security @ Cisco Blogs
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
Security Archives - TechRepublic
Security Archives - TechRepublic
Webroot Blog
Webroot Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Schneier on Security
S
Secure Thoughts
The Register - Security
The Register - Security
B
Blog RSS Feed
The Last Watchdog
The Last Watchdog
P
Palo Alto Networks Blog
爱范儿
爱范儿
B
Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
L
LINUX DO - 热门话题
C
Cisco Blogs
Spread Privacy
Spread Privacy
F
Full Disclosure
博客园 - 聂微东
T
The Blog of Author Tim Ferriss

博客园 - 赏梅斋

直接访问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.
}