I have an MVC 3 site that uses IoC (Unity), and my model is generated w/ EF4 and POCOs. I am using an action filter to commit my UnitOfWork:
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)
{
}
}
However, even though the Commit()
seems to be getting fired, it somehow seems to be caching what it thinks is "dirty".
For example, in my controller, the following gets executed from a service class:
var user = _userRepository.Single(u => u.Id == 2);
user.DateAdded = DateTime.Now;
Whenever I do a fresh build of the solution and hit this controller action, the change is actually committed. However, successive hits to the controller doesn't do anything.
On the other hand, if I put a UnitOfWork in my controller and commit it following the service method call, it works as expected (every time I request the controller action):
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();
}
So it definitely seems like some sort of c开发者_运维问答aching is going on, but I can't figure it out what is getting cached -- the UnitOfWork, the ActionFilter, or the repository.
Any ideas what could be going on? And if not, any ideas what else I could do to troubleshoot?
Thanks in advance.
You are initializing your unit of work in the constructor of the action filter which means that it will be injected when the action filter is instantiated. Quote from the ASP.NET MVC 3 release notes:
In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.
Make sure the dependency container returns the same instance in all places and rewrite the filter to avoid state caching:
public class UseUnitOfWorkAttribute : ActionFilterAttribute, IActionFilter
{
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
{
var unitOfWork = IoCFactory.Instance.CurrentContainer.Resolve<IUnitOfWork>();
unitOfWork.Commit();
}
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
}
}
I would check the lifetime on your repository. That was certainly the culprit in our implementation.
精彩评论