设为首页 收藏本站
查看: 839|回复: 0

[经验分享] SharePoint 2010开发最佳实践指南

[复制链接]

尚未签到

发表于 2015-9-29 07:36:41 | 显示全部楼层 |阅读模式
  摘要:
  本文基于SharePoint SDK文档,总结了开发者最佳实践,以对SharePoint2010开发提供指南。本指南覆盖2007以及2010两个版本,包括对SPSite和SPWeb对象的使用指南,系统Template文件夹下部署内容时的命名规范,事件处理器内SPWeb, SPSite对象使用、大文件夹以及大列表的处理、对象缓存以及代码优化的一些例子。
  避免使用构造不必要的SPWeb和SPSite对象
  1. SPWeb和SPSite会占用大量的内存,开发时尽量避免构造新的SPWeb和SPSite对象,特别是只是为了取得对SPWebApplication的引用等情况,为了取得SPWebApplication,可以调用SPWebApplication.Lookup(uri)来取得引用,接下类也可以通过webApplication.Farm来取得对farm的引用,进一步如果知道内容数据库的索引值,可以通过webApplication.ContentDatabase[index]来取得对内容数据库的引用。








view sourceprint?




1SPWebApplication webApplication = SPWebApplication.Lookup(new Uri("http://localhost/");



2SPFarm farm = webApplication.Farm;



3SPContentDatabase content = webApplication.ContentDatabases[0];
  2. 如果一定要构造SPWeb和SPSite对象,务必注意使用完后对象的释放,可以使用以下三种技术:
  Dispose方法
  using
  try, catch, finally
  使用using如下:








view sourceprint?




String str;



using(SPSite oSPsite = new SPSite("http://server/"))



{



  using(SPWeb oSPWeb = oSPSite.OpenWeb())



   {



       str = oSPWeb.Title;



       str = oSPWeb.Url;



   }



}
但是在使用的时候一定要特别注意,避免释放了不该释放的内容,比如:using( SPWeb web = SPControl.GetContextWeb(HttpContext.Current)) { ... }SPContext由SharePoint框架来进行维护,不应该释放,SPContext.Site, SPContext.Current.Site, SPContext.Web, SPContext.Current.Web同理也不能释放。try, catch, finally本质和using是一样,对实现了IDisposal接口的对象,.NET运行时环境会自动将using转换成try, catch, finally.







view sourceprint?




01String str;



02SPSite oSPSite = null;



03SPWeb oSPWeb = null;



04  



05try



06{



07   oSPSite = new SPSite("http://server/");



08   oSPWeb = oSPSite.OpenWeb(..);



09  



10   str = oSPWeb.Title;



11}



12catch(Exception e)



13{



14   //Handle exception, log exception, etc.



15}



16finally



17{



18   if (oSPWeb != null)



19     oSPWeb.Dispose();



20  



21   if (oSPSite != null)



22      oSPSite.Dispose();



23}
  页面重定向时候的资源释放:如下例,在Response.Redirect调用时会生成ThreadAbortedException异常,而之后finally会被执行,此时会导致线程的异常,无法保证资源一定会得到释放,因此在任何Response.Redirect调用之前一定要确保SPSite,SPWeb对象的释放








view sourceprint?




01String str;



02SPSite oSPSite = null;



03SPWeb oSPWeb = null;



04  



05try



06{



07   oSPSite = new SPSite("http://server/");



08   oSPWeb = oSPSite.OpenWeb(..);



09  



10   str = oSPWeb.Title;



11   if(bDoRedirection)



12   {



13       if (oSPWeb != null)



14          oSPWeb.Dispose();



15      



16       if (oSPSite != null)



17          oSPSite.Dispose();



18  



19       Response.Redirect("newpage.aspx");



20   }



21}



22catch(Exception e)



23{



24}



25finally



26{



27   if (oSPWeb != null)



28     oSPWeb.Dispose();



29  



30   if (oSPSite != null)



31      oSPSite.Dispose();



32}
  以上问题也适用于using。
  不要创建静态的SPWeb和SPSite对象
  调用SPSiteCollection.Add方法创建返回的SPSite对象需要释放;
  通过SPSiteColleciton的索引器SPSiteColleciton[]返回的SPSite对象需要释放;
  在SPSiteCollection集合中进行foreach是的SPSite对象需要释放;
  以下是推荐的做法:








view sourceprint?




01void SPSiteCollectionForEachNoLeak()



02{



03    using (SPSite siteCollectionOuter = new SPSite("http://moss/"))



04    {



05        SPWebApplication webApp = siteCollectionOuter.WebApplication;



06        SPSiteCollection siteCollections = webApp.Sites;



07  



08        foreach (SPSite siteCollectionInner in siteCollections)



09        {



10            try



11            {



12                // ...



13            }



14            finally



15            {



16                if(siteCollectionInner != null)



17                    siteCollectionInner.Dispose();



18            }



19        }



20    } // SPSite object siteCollectionOuter.Dispose() automatically called.



21}
  通过SPSite.AllWebs.Add返回的SPWeb对象需要释放;
  通过SPWebColleciton.Add返回的SPWeb对象需要释放;
  通过SPSite.AllWebs[]索引器返回的SPWeb对象需要释放;
  通过foreach循环SPWebColleciton的SPWeb对象需要释放;
  通过OpenWeb打开的SPWeb对象需要释放;
  通过SPSite.SelfServiceCreateSite创建的SPWeb对象需要释放;
  SPSite.RootWeb不需要进行释放;
  通过Microsoft.Office.Server.UserProfiles.PersonalSite返回的SPSite对象需要释放;
推荐的开发方式如下:



view sourceprint?

01void PersonalSiteNoLeak()

02{

03    // Open a site collection

04    using (SPSite siteCollection = new SPSite("http://moss/"))

05    {

06        UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));

07        UserProfile profile = profileManager.GetUserProfile("domain\\username");

08        using (SPSite personalSite = profile.PersonalSite)

09        {

10            // ...

11        }

12    }

13}

此处可以通过ProfileLoader省去构造新的SPSite以提高性能







view sourceprint?




1UserProfile myProfile = ProfileLoader.GetProfileLoader().GetUserProfile();



2using (SPSite personalSite = myProfile.PersonalSite)



3{



4     // ...



5}
  特别,如果为MySite创建web部件,可以使用PersonalSite而不用释放:








view sourceprint?




1IPersonalPage currentMySitePage = this.Page as IPersonalPage;  



2if (currentMySitePage != null && !currentMySitePage.IsProfileError)  



3{  



4    SPSite personalSite = currentMySitePage.PersonalSite; // Will not leak. // ...  



5}
  通过GetContextSite返回的SPSite不需要释放




view sourceprint?

1void SPControlBADPractice()

2{

3    SPSite siteCollection = SPControl.GetContextSite(Context);

4    //siteCollection.Dispose();   不要释放

5    SPWeb web = SPControl.GetContextWeb(Context);

6    //web.Dispose();  不要释放

7}

SPLimitedWebPartManager含有内部对SPWeb的引用,需要释放



view sourceprint?

01void SPLimitedWebPartManagerLeak()

02{

03    using (SPSite siteCollection = new SPSite("http://moss/"))

04    {

05        using (SPWeb web = siteCollection.OpenWeb())

06        {

07            SPFile page = web.GetFile("Source_Folder_Name/Source_Page");

08            SPLimitedWebPartManager webPartManager =

09                page.GetLimitedWebPartManager(PersonalizationScope.Shared);

10                webPartManaber.Web.Dispose();

11        } // SPWeb object web.Dispose() automatically called.

12    }  // SPSite object siteCollection.Dispose() automatically called.  

13}

Microsoft.SharePoint.Publishing.PublishingWeb(SharePoint2007 only)
  PublishingWeb.GetPublishingWebs会返回PublishingWebCollection,foreach时候需要调用close方法释放每一个对象:








view sourceprint?




01void PublishingWebCollectionNoLeak()



02{



03    using (SPSite siteCollection = new SPSite("http://moss/"))



04    {



05        using (SPWeb web = siteCollection.OpenWeb())



06        {



07            // Passing in SPWeb object that you own, no dispose needed on



08            // outerPubWeb.



09            PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);



10            PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();



11            foreach (PublishingWeb innerPubWeb in pubWebCollection)



12            {



13                try



14                {



15                    // ...



16                }



17                finally



18                {



19                    if(innerPubWeb != null)



20                        innerPubWeb.Close();



21                }



22            }



23        }  // SPWeb object web.Dispose() automatically called.



24    } // SPSite object siteCollection.Dispose() automatically called.



25}
  同样,调用PublishingWebCollection.Add返回的PublishingWeb也需要释放;
  3.在事件处理器里可以使用以下方法避免生成新的SPSite或者SPWeb








view sourceprint?




1// Retrieve SPWeb and SPListItem from SPItemEventProperties instead of  



2// from a new instance of SPSite.  



3SPWeb web = properties.OpenWeb();//此处通过properties.OpenWeb()返回的SPWeb不用释放;  



4// Operate on the SPWeb object.  



5SPListItem item = properties.ListItem;  



6// Operate on an item.
  文件名限制:
  在实战中如果需要部署文件夹或者文件到%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE目录,出于安全考虑,SharePoint Foundation只能够读取文件名有ASCII字符、数字、下划线、句号、破折号(dashed)组成的名字,特别是文件名不能包括两个连续的句号,例如,以下是允许的文件名:
  AllItems.aspx
  Dept_1234.doc
  Long.Name.With.Dots.txt
  以下是不允许的名字:
  Cæsar.wav
  File Name With Spaces.avi
  Wow...ThisIsBad.rtf
  揵.htm
  大文件夹、大列表的处理
  不要使用SPList.Items,因为这个调用会返回所有子文件夹下的所有记录,使用以下方法替代:
  添加记录:使用SPList.AddItem,不使用SPList.Items.Add;
  查询记录:使用SPList.GetItemById,不适用SPList.Items.GetItemById;
  返回列表所有记录:使用SPList.GetItems(SPQuery query)而不是SPList.Items,根据需要使用条件过滤,仅仅挑选必要的字段返回,如果返回结果超过2000条,采用分页技术:








view sourceprint?




01SPQuery query = new SPQuery();



02SPListItemCollection spListItems ;  string lastItemIdOnPage = null; // Page position.



03int itemCount = 2000   while (itemCount == 2000)



04{



05    // Include only the fields you will use.



06    query.ViewFields = "<FieldRef Name=\"ID\"/><FieldRef Name=\"ContentTypeId\"/>";   query.RowLimit = 2000; // Only select the top 2000.



07    // Include items in a subfolder (if necessary).



08    query.ViewAttributes = "Scope=\"Recursive\"";



09    StringBuilder sb = new StringBuilder();



10    // To make the query order by ID and stop scanning the table, specify the OrderBy override attribute.



11    sb.Append("<OrderBy Override=\"TRUE\"><FieldRef Name=\"ID\"/></OrderBy>");



12    //.. Append more text as necessary ..



13    query.Query = sb.ToString();   // Get 2,000 more items.   SPListItemCollectionPosition pos = new SPListItemCollectionPosition(lastItemIdOnPage);



14    query.ListItemCollectionPosition = pos; //Page info.



15    spListItems = spList.GetItems(query);



16    lastItemIdOnPage = spListItems.ListItemCollectionPosition.PagingInfo;



17    // Code to enumerate the spListItems.



18    // If itemCount <2000, finish the enumeration.



19    itemCount = spListItems.Count;



20  



21}
  分页显示:








view sourceprint?




01SPWeb oWebsite = SPContext.Current.Web;



02SPList oList = oWebsite.Lists["Announcements"];



03  



04SPQuery oQuery = new SPQuery();



05oQuery.RowLimit = 10;



06int intIndex = 1;



07  



08do



09{



10    Response.Write("<BR>Page: " + intIndex + "<BR>");



11    SPListItemCollection collListItems = oList.GetItems(oQuery);



12  



13    foreach (SPListItem oListItem in collListItems)



14    {



15        Response.Write(SPEncode.HtmlEncode(oListItem["Title"].ToString()) +"<BR>");



16    }



17  



18    oQuery.ListItemCollectionPosition = collListItems.ListItemCollectionPosition;



19    intIndex++;



20} while (oQuery.ListItemCollectionPosition != null);

  性能差不推荐使用的API
  性能更好的推荐使用的API
  SPList.Items.Count
  SPList.ItemCount
  SPList.Items.XmlDataSchema
创建SPQuery,仅仅返回需要的数据
  SPList.Items.NumberOfFields
创建SPQuery,指定ViewFields,仅仅返回需要的数据
  SPList.Items[System.Guid]
  SPList.GetItemByUniqueId(System.Guid)
  SPList.Items[System.Int32]
  SPList.GetItemById(System.Int32)
  SPList.Items.GetItemById(System.Int32)
  SPList.GetItemById(System.Int32)
  SPList.Items.ReorderItems(System.Boolean[],System.Int32[],System.Int32)
使用SPQuery分页
  SPList.Items.ListItemCollectionPosition
  ContentIterator.ProcessListItems(SPList, ContentIterator.ItemProcessor, ContentIterator.ItemProcessorErrorCallout) (Microsoft SharePoint Server 2010 only)
  参考:
  释放检查工具SPDisposeCheck: http://code.msdn.microsoft.com/SPDisposeCheck
  http://msdn.microsoft.com/en-us/library/aa973248(office.12).aspx
  http://msdn.microsoft.com/en-us/library/bb687949%28office.12%29.aspx

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-120141-1-1.html 上篇帖子: sharepoint安装 下篇帖子: 在webpart中使用updatepanel控件,并在sharepoint中实现ajax局部刷新
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表