sharepoint - SPWeb.Site, ¿debería llamar a Dispose() en él?
(8)
Actualizado 06/08/2009 15:52 : Respuesta corta NO . Pregunta original:
No puedo encontrar ninguna referencia que brinde orientación en SPWeb.Site con respecto a la eliminación. He revisado algunos de los documentos de prácticas más populares sobre cómo desechar objetos de SharePoint:
- http://www.sharepointdevwiki.com/display/public/When+to+Dispose+SharePoint+objects
- http://msdn.microsoft.com/en-us/library/aa973248.aspx
- http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx
Desafortunadamente, ninguna de estas directrices menciona SPWeb.Site. Para dar un poco de contexto, estoy escribiendo una API de extensión pública que acepta un SPWeb como un argumento para un método, es decir:
public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)
{
......
SPSite site = web.Site;
......
**OR** ??
using (SPSite site = web.Site)
{
....
}
}
He mirado como el método Cerrar () en el refelector para SPWeb, al que llama SPWeb.Dispose () y no hay nada en él que indique que se ha eliminado el campo real del miembro SPSite.
Actualización: 06/08/2009 13:47
A sugerencia Alex''s
"Póngalo en un bucle que se ejecute 100 veces y use la clave de registro SPRequestStackTrace que se describe en Solución de problemas de las fugas de SPSite / SPWeb en WSS v3 y MOSS 2007 para verificar que su código de prueba sea la fuente del problema".
Corrí la siguiente pieza de código incluida dentro de un webpart:
for (int i = 0; i < 100; i++)
{
using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
{
SPSite site = web.Site;
Debug.WriteLine(site.Url);
}
}
Nada apareció en los registros de SharePoint.
Si bien dudaría en sacar conclusiones reales de este experimento ingenuo, sugeriría que no es necesario deshacerse de SPWeb.Site. Sería muy bueno obtener una respuesta concreta de alguien más informado sobre este tema.
Actualización: 06/08/2009 14:52 Solicitado por el comentario de Greg Resolví las asignaciones de m_Site y parece que, en última instancia, siempre se pasa a SPWeb a través de los constructores internos. Por ejemplo, SPWeb.OpenWeb pasa esto a nuevo SPWeb (). Así que estoy más seguro de que SPWeb.Site no debe eliminarse, de hecho podría causar problemas si lo fuera.
¿Ha intentado comprobar su montaje con SPDisposeCheck ? Tal vez le da una sugerencia de cómo manejar su problema.
A menudo utilizo este patrón en mi código de SharePoint como una regla de oro si el depósito de llamada no bloquea nada de lo que yo llamo. La otra regla que sigo es que trato de no crear extensiones que no causen una ganancia neta en los objetos SPRequest
(el objeto SPRequest
es el objeto .net que habla con todos los objetos de peso pesado)
ahora rompiendo tu ejemplo
for (int i = 0; i < 100; i++)
{
using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
{
SPSite site = web.Site;
Debug.WriteLine(site.Url);
}
}
La clave aquí es el SPContext.Current.Site
El SPContext
se limpiará automáticamente (uno de los pocos objetos que lo hace), ya que sabemos que el sitio se limpió correctamente. Supongo que las redes se limpiaron, sin embargo, esto está lejos de la respuesta correcta a su pregunta. (Tenga en cuenta que debería estar filtrando las webs que obtuvo a través de OpenWeb)
public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)
necesita obtener el SPSite
para hacer algo con las partes web.
- de hecho, la propiedad del sitio web se limpia después de que sea propia SI la web está dispuesta.
- ¿Por qué no simplemente pasar el objeto SPSite y dejar que el usuario de la función se preocupe por eso? En la mayoría de los casos, creo que estarían llamando usando SPContext.Current.Site de todos modos.
- La mayoría de las veces tengo que preocuparme por los permisos, no todos los dlls terminan en el GAC, por lo que cuando escribo un nuevo método de extensión, tengo que
SPSecurity.CodeToRunElevated
unSPSecurity.CodeToRunElevated
Con eso en mente terminaría escribiendo esto como. . . ahora el control de Disposición se activará en este caso porque el SPSite se pasa como un argumento porque no puede rastrear en qué alcance se encuentra.
public static void GetWebPartFromCatalog(this SPSite site, string webPartName) {
SPSecurity.CodeToRunElevated( () => {
using(SPSite suSite = new SPSite(site.Id)){
//do what you need to do
}
};
}
Debe eliminar la instancia de SPSite / SPWeb si es un nuevo objeto
p.ej
using(SPSite site = new SPSite("url"))
{
DoSomething;
}
Aquí, el uso se encargará de eliminar el objeto; sin embargo, si obtuvo la referencia del objeto desde SPContext.Current, no debe eliminar el objeto explícitamente, ya que la referencia debería estar disponible desde SPContext.Current.
Esto no está claro. Hay un blog de Stefan que dice "Debe asegurarse de que solo elimine los objetos SPSite y SPWeb que posee su código" . Luego está este hilo de Michael Washam (Microsoft) que indica que este patrón no se filtra.
A menos que pueda encontrar otra referencia o alguien más lo sepa, ¿por qué no lo prueba en su servidor de desarrollo y agrega sus resultados como respuesta a esta pregunta? Póngalo en un bucle que se ejecute 100 veces y use la clave de registro SPRequestStackTrace que se describe en Solución de problemas de las fugas de SPSite / SPWeb en WSS v3 y MOSS 2007 para verificar que su código de prueba sea la fuente del problema.
Reflector nos dice que este es el código que se ejecuta dentro del objeto SPWeb cuando llama a la propiedad del sitio:
public SPSite Site
{
get
{
return this.m_Site;
}
}
No está creando un nuevo objeto SPSite, simplemente devolviendo el que ya tenía, lo que dependería de SPWeb.Dispose () para cuidar, si es necesario. Por lo tanto, puede usarlo de manera segura, y yo evitaría deshacerme de él, para que las dependencias de SPWeb no sean tan fáciles.
Solo pensando en lo alto de mi cabeza (a veces peligroso) ...
Parece que realmente no puedes tener un SPWeb sin tener un SPSite. Por lo tanto, si obtuvo el SPWeb sin pasar por SPSite para obtenerlo (ya sea haciendo un nuevo SPSite o uno que se le proporcione), entonces probablemente no deba preocuparse por deshacerse del SPSite.
Sin embargo, esto es solo una conjetura. ¡Buena pregunta!
Stefan Gobner tiene un excelente artículo sobre esto: Solución de problemas de fugas de SPSite / SPWeb en WSS v3 y MOSS 2007
... Y asegúrese de usar la herramienta de verificación SPDispose en su código base.
La respuesta de Kirk es correcta. Debe tener un identificador de un SPSite antes de poder crear un SPWeb, y esa es la misma instancia de SPSite que tendrá cuando llame a SPWeb.Site.
Pensemos en las implicaciones de eso: si no controlas la creación del SPSite, pero una de sus webs secundarias se te entrega desde un código externo, y eliminas el sitio, cuando el control se devuelve al código de llamada, ¡He eliminado un sitio con el que no se puede hacer! Póngase en el lugar del código de llamada: pasa un SPWeb a un método, y cuando se realiza ese método, se cerró el SPSite que estaba usando. Siempre es responsabilidad del instanciador limpiar los recursos que asignan. No deseche el SPSite en este caso.