Estoy pasando por una gran refactorización / ajuste de velocidad de una de mis aplicaciones MVC más grandes. Se ha implementado en producción desde hace unos meses y estaba empezando a tener tiempos de espera esperando conexiones en el grupo de conexiones. He rastreado el problema hasta que las conexiones no se eliminan correctamente.
A la luz de eso, desde entonces hice este cambio en mi controlador base:
public class MyBaseController : Controller
{
private ConfigurationManager configManager; // Manages the data context.
public MyBaseController()
{
configManager = new ConfigurationManager();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.configManager != null)
{
this.configManager.Dispose();
this.configManager = null;
}
}
base.Dispose(disposing);
}
}
Ahora tengo dos preguntas:
- ¿Estoy introduciendo una condición de carrera? Dado que
configManager
administra elDataContext
que expone losIQueryable<>
parámetros a las vistas, necesito asegurarme de queDispose()
no se llamará en el controlador antes de que la vista termine de renderizarse. - ¿El marco MVC llama
Dispose()
al controlador antes o después de que se renderice la vista? ¿O el marco MVC deja eso en manos de GarbageCollector?
asp.net-mvc
linq-to-sql
garbage-collection
idisposable
John Gietzen
fuente
fuente
Respuestas:
Se llama a Dispose después de renderizar la vista, siempre .
La vista se representa en la llamada a
ActionResult.ExecuteResult
. Eso es llamado (indirectamente) porControllerActionInvoker.InvokeAction
, que a su vez es llamado porControllerBase.ExecuteCore
.Dado que el controlador está en la pila de llamadas cuando se representa la vista, no se puede eliminar en ese momento.
fuente
Solo para ampliar la respuesta de Craig Stuntz :
ControllerFactory maneja cuando se elimina un controlador. Al implementar la interfaz IControllerFactory, uno de los métodos que debe implementarse es ReleaseController.
No estoy seguro de qué ControllerFactory está usando, ya sea que haya rodado el suyo, pero en Reflector mirando DefaultControllerFactory, el método ReleaseController se implementa así:
public virtual void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } }
Se pasa una referencia de IController, si ese controlador implementa IDisposable, entonces se llama al método Dispose de los controladores. Por lo tanto, si tiene algo que necesite eliminar después de que finalice la solicitud, que es después de que se procese la vista. Herede IDisposable y ponga su lógica en el método Dispose para liberar cualquier recurso.
El método ReleaseController es llamado por System.Web.Mvc.MvcHandler que maneja la solicitud e implementa IHttpHandler. ProcessRequest toma el HttpContext que se le ha dado e inicia el proceso de encontrar el controlador para manejar la solicitud, llamando al ControllerFactory implementado. Si observa el método ProcessRequest, verá el bloque finalmente que llama al ReleaseController de ControllerFactory. Esto solo se llama cuando el controlador ha devuelto un ViewResult.
fuente
HttpContext
es un hombre? Ahora estoy realmente confundido.