12

Tengo un sitio MVC 3 que usa IoC (Unity) y mi modelo se genera con EF4 y POCO. Estoy utilizando un filtro de acción para comprometer mi UnitOfWork:UnitOfWork in Action El filtro parece estar en caché

public class UseUnitOfWorkAttribute : ActionFilterAttribute, IActionFilter 
{ 
    private readonly IUnitOfWork _unitOfWork; 

    public UseUnitOfWorkAttribute() 
    { 
     _unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
    } 

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     _unitOfWork.Commit(); 
    } 

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    } 
} 

Sin embargo, a pesar de que la Commit() parece ser cada vez disparado, de alguna manera parece ser el almacenamiento en caché lo que cree que es "sucio".

Por ejemplo, en mi controlador, el siguiente es ejecutado de una clase de servicio:

var user = _userRepository.Single(u => u.Id == 2); 
user.DateAdded = DateTime.Now; 

Cada vez que hago una construcción nueva de la solución y golpear esta acción del controlador, el cambio que realmente se cometa. Sin embargo, las visitas sucesivas al controlador no hacen nada.

Por otro lado, si pongo un UnitOfWork en mi controlador y COMPROMÉTANSE siguiendo el llamado método de servicio, que funciona como se espera (cada vez que lo solicite la acción del controlador):

public AccountController() 
{ 
    _unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
} 

public ActionResult Test() 
{ 
    var user = _userRepository.Single(u => u.Id == 2); 
    user.DateAdded = DateTime.Now; 
    _unitOfWork.Commit(); 
} 

por lo que definitivamente parece que está ocurriendo algún tipo de almacenamiento en caché, pero no puedo entender qué se almacena en caché: UnitOfWork, ActionFilter o el repositorio.

¿Alguna idea de lo que podría estar pasando? Y si no, ¿qué ideas podría hacer para solucionarlo?

Gracias de antemano.

Respuesta

26

Está inicializando su unidad de trabajo en el constructor del filtro de acción, lo que significa que se inyectará cuando se crea una instancia del filtro de acción. Presupuesto de la ASP.NET MVC 3 release notes:

En las versiones anteriores de ASP.NET MVC, filtros de acción fueron creados por solicitud, excepto en unos pocos casos. Este comportamiento nunca fue un comportamiento garantizado, sino simplemente un detalle de implementación y el contrato de filtros los consideró apátridas. En ASP.NET MVC 3, los filtros se almacenan en caché más agresivamente. Por lo tanto, cualquier filtro de acción personalizado que almacene incorrectamente el estado de instancia podría estar roto.

+0

Gracias, esto es excatly lo que está pasando. Traté de encontrar información sobre el almacenamiento en memoria caché del filtro de acción, pero nunca encontré esto en mis búsquedas. –

+0

¡Buena captura, @Darin! – neontapir

+0

Ojalá pudiera votar esto 5 veces. Killer al actualizar aplicaciones MVC 1/2. – Paul

0

Verificaría la vida útil de su repositorio. Ese fue sin duda el culpable de nuestra implementación.

+0

estoy usando 'TransientLifetimeManager()' en mis repositorios. Mi ObjectContext y UnitOfWork usan un 'PerExecutionContextLifetimeManager()' personalizado, que es básicamente por duración de la solicitud. ¿Mis repositorios también deberían ser 'PerExecutionContextLifetimeManager()'? –

+0

Actualización: Acabo de intentarlo, solo para descartarlo, y el uso de 'PerExecutionContextLifetimeManager()' también parece tener los mismos resultados. ¿Hay otras opciones que deba probar? –

6

Asegúrese de que el contenedor de la dependencia devuelve la misma instancia en todos los lugares y volver a escribir el filtro para evitar el almacenamiento en caché de estado:

public class UseUnitOfWorkAttribute : ActionFilterAttribute, IActionFilter 
{ 
    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     var unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>(); 
     unitOfWork.Commit(); 
    } 

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    } 
} 
+0

Gracias, esta solución funciona. –

Cuestiones relacionadas