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

来源:互联网 发布:深圳市软件测试培训 编辑:程序博客网 时间:2024/05/23 10:24

      有的时候在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. 另一个错误释放的例子:点击打开链接

原创粉丝点击