SharePoint log分析——“Detected use of SPRequest for previously closed SPWeb object. ”

      有的时候在SharePoint的log中会发现这样的log信息:

      Detected use of SPRequest for previously closed SPWeb object.  
      Please close SPWeb objects when you are done with all objects obtained from them, but not before.  
      这个错误信息与SPSite、SPWeb这种非托管的对象没有正确释放有关系,或者释放早了,或者释放晚了,或者把不应该释放的给释放了。

      以下是正确释放SPSite、SPWeb非托管对象的一些规则(摘录并翻译自《SharePoint 2010 as a Development Platform》):

      1.当你释放一个SPSite对象的时候,通过这个SPSite获取的所有SPWeb对象都将被释放。

      2.用SPSite/SPWeb对象的时候就创建,不用的时候就释放,宁可多次创建和释放也不要一直不释放。

      3.使用using来确保SPSite/SPWeb对象的释放,以下是一个正确创建和释放的例子:

    void GetList(string webUrl, string listName)
    {
        using(SPSite site = new SPSite(webUrl))
        {
            using(SPWeb web = site.openWeb())
            {
                 try
                 {
                      GetListHelper(web, listName);
                 }
                 catch{}  
            }
        }
    }
    void GetListHelper(SPWeb web, string listName)
    {
        SPList list = web.Lists[listName];
        ...
    }

      4.只释放你自己创建的SPSite和SPWeb对象。

      5.通过GetLimitedWebPartManager获得的SPLimitedWebPartManager对象会引用一个SPWeb对象,这种情况下,需要显式的释放掉它:      

      SPFile page = web.GetFile("default.aspx");
      using (SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
      {
          try
          {
              // Do stuff
          }
          finally
          {
              webPartManager.Web.Dispose(); 
          }
      }
      6.不要释放下列的属于SharePoint的SPSite和SPWeb对象:

      SPSite site = SPContext.Current.Site;
      SPWeb rootWeb = site.RootWeb;
      SPWeb web = SPContext.Web;
      SPWeb web = SPContext.Current.Web;
      SPSite site = SPContext.Site;
      SPSite site = SPContext.Current.Site;

      7.在遍历子站点集合的时候需要显式释放SPWeb对象例如:

      foreach (SPWeb subweb in rootweb.Webs)
      {
          // Do stuff
      }
      这段代码遍历了子站点集合,在执行的过程中,SharePoint会隐式调用OpenWeb方法,因此正确的方法是显式的释放SPWeb对象:

      for (int i = 0; i <= rootweb.Webs.Count; i++)
      {
          using (SPWeb subweb = rootweb.Webs[i])
          {
                // Do stuff
          }
      }
      或者:
      foreach (SPWeb subweb in rootweb.Webs)
      {
          try
          {
               // Do stuff
          }
          finally
          {
               subweb.Dispose();
          } 
      }

      8.在使用Feature Receiver的时候,SPFeatureReveiverProperties.Feature.Parent 如果是SPWeb或者SPSite对象,不应该被释放:

      public override void FeatureActivated(SPFeatureReceiverProperties properties)
      {
            SPWeb web = properties.Feature.Parent as SPWeb;
          // Do stuff
      }
      以下Event Receiver使用的对象,也不需要释放:

      SPWebEventProperties.Web
      SPListEventProperties.Web
      SPListEventProperties.List.Web  
      SPItemEventProperties.ListItem.Web
      其中的SPItemEventProperties对象是实现了IDisposable接口的,其他的没有实现这个接口。虽然SPItemEventProperties对象实现了IDisposable接口,但是,我们并不知道SharePoint是否正确地释放了它所引用的SPSite对象,所以安全的方法是,我们自己创建SPSite对象,然后显式地释放:

      public override void ItemAdded(SPItemEventProperties properties)     
      {
          using (SPSite site = new SPSite(properties.WebUrl))
          {
               using(SPWeb web = site.OpenWeb())
               {
                   SPList list = web.Lists[properties.ListId];
                   SPListItem item = list.GetItemById(properties.ListItemId);
                   // Do stuff
               }
          }
          base.ItemAdded(properties);
      }
      9.Microsoft.SharePoint.Portal.WebControls.IPersonalPage 有两个属性IPersonalPage.PersonalSite 和IPersonalPage.PersonalWeb,这两个属性不需要释放,以下方法的返回值也是这俩个对象其中之一,一样不需要释放:

      UnsecuredLayoutsPage.Web
      LayoutsPageBase.Web
      SPControl.GetContextWeb()
      SPControl.GetContextSite()   
      SPWebProvisioningProperties.Web
     10.有一个特殊的属性:SPWeb.ParentWeb。这个对象可能是SharePoint创建的,也可能是开发人员创建的(这里的创建是指在第一次调用这个属性的时候,SharePoint会为它创建一个SPWeb对象)。如果SPWeb对象是属于SharePoint的,那么SPWeb.ParentWeb也是属于SharePoint的,不需要释放。

     11.以下是两个错误释放的例子:

public static SPWeb GetSPWeb(string url)
      {
          using (var site = new SPSite(url))
          {
              using (SPWeb web = site.OpenWeb())
              {
                  return web;
              }
          }
      }

public static SPList GetSPList(string url, Guid listID)
      {
	  SPList list = null;
          using (var site = new SPSite(url))
          {
              using (SPWeb web = site.OpenWeb())
              {
                  list = web.Lists[listID];
              }
          }
	  return list;
      }

这样返回的list,其parentWeb已经被释放了,当调用list.ParentWeb的时候,就会报错。

    12. 另一个错误释放的例子:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值