Disposing objects in SharePoint 2010

En SharePoint 2010 contamos con los siguientes objetos:

  • SPFarm
  • SPService
  • SPWebApplication
  • SPSite
  • SPWeb
  • SPList

La mayoría de los cuales no soportan o requieren Dispose. SharePoint 2010 cuenta con una gran cantidad de productos, algunos de ellos fueron creados incluso antes de que .NET existiera. Los objetos SPSite y SPWeb se apoyan en ciertos (no todos) objetos COM para llevar a cabo su funcionalidad. Entonces, el recolector de basura no nos asegurará el liberar todos los recursos para los SPWeb y SPSite no referenciados en memoria. La no liberación de estos recursos es un error común en el desarrollo en SharePoint.

¿Cómo liberaremos los recursos?

Estos objetos implementan la la interfaz IDispose, la cual utilizaremos para liberarlos.

¿Qué sucede si no se realiza Dispose?

El recolector de basura tendría que encargarse de la liberación de estos recursos pero como ya se menciono, no lo realizará totalmente y dejaremos estos objetos colgados en memoria con lo cual causaremos un memory leak en nustro servidor.

Best practices para la liberacion de recursos de SPSite y SPWeb

La forma de liberar los recursos depende de la forma en que instanciamos nuestro objeto:

Si creas una nueva instancia de un SPSite o SPWeb, debes de realizar un Dispose cuando ya no se necesite el objeto.

SPSite site= new SPSite("http://sharepoint");

SPWeb web= mySite.OpenWeb("/projects");

...

web.Dispose();

site.Dispose();

Cuando recorremos en un foreach una lista de objetos SPSite o SPWeb, en cada interación del foreach se instancia el SPSite o SPWeb correspondiente. Por tanto, debemos de realizar un Dispose al final de su uso.

...
foreach (SPSite site in webApplication.Sites)
{
   try
   {
   ...
   }
   finally
   {
      site.Dispose();
   }
}

Una forma de realizar Dispose automáticamente a los objetos cuando dejen de utilizarse es poner nuestro código dentro de un bloque Using. Using automáticamente libera el objeto cuando el código dentro del bloque se ha ejecutado.


using(SPSite site = new SPSite("http://sharepoint"))
{
   using(SPWeb web = site.RootWeb)
   {
    ...
   }
}

Si utilizas las instancias globales de SPSite y SPWeb que provee la clase estática SPContext.Current no hay que realizar un Dispose a estos objetos ya que son para uso global y otros componentes los utilizan.

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

//No realizar Dispose a estos objetos