entity framework 4 - Ninject no llama a Dispose en objetos cuando está fuera de alcance
entity-framework-4 asp.net-mvc-3 (1)
Ninject eliminará sus objetos tan pronto como el GC recoja el objeto solicitado. Pero normalmente esto lleva algo de tiempo. Pero hay una forma de forzar la eliminación anticipada después de que la solicitud finalizó. La mejor manera es usar Ninject.Web.MVC http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ lugar de implementar su propio ControllerFactory. La otra forma es configurar su aplicación para usar el OnePerRequestModule.
Me sorprendió descubrir que al menos uno de mis objetos creados por Ninject no se descarta al final de la solicitud, cuando se ha definido como InRequestScope
Este es el objeto que trato de eliminar:
Interfaz:
public interface IDataContext : IDisposable
{
MessengerEntities context { get; set; }
}
MessengerEntities es la implementación de ObjectContext de Entity Framework: mi objeto de contexto.
Luego creo una clase concreta como esta:
public class DataContext : IDataContext
{
private MessengerEntities _context = new MessengerEntities();
public MessengerEntities context
{
get
{
return _context;
}
set
{
_context = value;
}
}
#region IDisposable Members
public void Dispose()
{
context.Dispose();
}
#endregion
}
Y luego tengo una fábrica de controladores Ninject como tal (esto está modelado en el libro Steve Sanderson MVC 2):
public class NinjectControllerFactory : DefaultControllerFactory
{
// a Ninject "kernel" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new MessengerServices());
// ASP.NET MVC calls this to get the controller for each request
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class MessengerServices : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<DataContext>().InRequestScope();
Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
}
}
}
Ahora, cuando pongo un punto de interrupción en la llamada a context.Dispose () en el objeto DataContext y ejecuto el depurador, ese código nunca se ejecuta.
Por lo tanto, la evidencia sugiere que Ninject no se deshace de los objetos cuando salen del alcance, sino que simplemente crea nuevos objetos y confía en el recolector de basura para deshacerse de ellos en el momento que elija.
Mi pregunta es: ¿debería preocuparme por esto? Debido a que lo soy, creo que Ninject eliminaría cualquier objeto que implemente IDisposable.
ACTUALIZACIÓN: descargué las extensiones Ninject Mvc (para MVC 3) y así es como estoy haciendo la aplicación Mvc y la vinculación, y parece que estoy desechando mi objeto de contexto.
En global.asax:
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
y
public class EFBindingModule : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<DataContext>().InRequestScope();
Bind<IArchivesRepository>().To<ArchivesRepository>().InRequestScope();
Bind<IMessagesRepository>().To<MessagesRepository>().InRequestScope();
}
}
Todo lo demás se mantiene igual.