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를 통해 가져온 모든 SP웹 객체가 해제됩니다.
      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 및 SP웹 객체만 놓습니다.
      5.GetLimitedWebPartManager를 통해 얻은 SPLimitedWebPartManager 객체는 SP웹 객체를 참조합니다. 이 경우 명시적으로 해제해야 합니다.
      SPFile page = web.GetFile("default.aspx");
      using (SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
      {
          try
          {
              // Do stuff
          }
          finally
          {
              webPartManager.Web.Dispose(); 
          }
      }
      6.SharePoint에 속하는 다음 SPSite 및 SP웹 객체는 해제하지 마십시오.
      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.하위 사이트 컬렉션을 이동할 때는 다음과 같이 SP웹 객체를 명시적으로 해제해야 합니다.
      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를 사용할 때 SPFeature Reveiver Properties.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
그 중의 SPItem EventProperties 대상은 IDisposable 인터페이스를 실현했고 다른 것은 이 인터페이스를 실현하지 못했다.SPItem Event Properties 대상이 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.Personal Site와 IPersonal Page.PersonalWeb은 두 속성을 해제할 필요가 없으며 다음 메서드의 반환 값도 두 객체 중 하나이며 마찬가지로 해제할 필요가 없습니다.
      UnsecuredLayoutsPage.Web
      LayoutsPageBase.Web
      SPControl.GetContextWeb()
      SPControl.GetContextSite()   
      SPWebProvisioningProperties.Web
     10.SPWeb.ParentWeb.이 대상은SharePoint에서 만들었을 수도 있고 개발자가 만들었을 수도 있습니다. (이 속성을 처음 호출했을 때SharePoint에서 SPweb 대상을 만들었습니다.)SPWeb 객체가 SharePoint에 속하는 경우 SPWeb.Parent Web도 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를 호출할 때 방출되었습니다.Parent Web 에서는 오류 메시지가 표시됩니다.
    12. 다른 오류 방출의 예: 링크를 열려면 누르십시오

좋은 웹페이지 즐겨찾기