UnitOfWork в действии Фильтр, похоже, кэширует

У меня есть сайт MVC 3, который использует IoC (Unity), и моя модель создается с EF4 и POCO. Я использую фильтр действий, чтобы зафиксировать свой 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)
    {
    }
}

Однако, несмотря на то, что Commit(), кажется, увольняется, он каким-то образом кэширует то, что считает «грязным».

Например, в моем контроллере из класса обслуживания выполняется следующее:

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

Всякий раз, когда я делаю новую сборку решения и нажимаю это действие контроллера, изменение фактически фиксируется. Однако последовательные обращения к контроллеру ничего не делают.

С другой стороны, если я помещаю UnitOfWork в свой контроллер и фиксирую его после вызова метода службы, он работает так, как ожидалось (каждый раз, когда я запрашиваю действие контроллера):

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();
}

Таким образом, определенно кажется, что происходит какое-то кеширование, но я не могу понять, что кешируется — UnitOfWork, ActionFilter или репозиторий.

Любые идеи, что может происходить? И если нет, какие идеи еще я мог бы сделать, чтобы устранить неполадки?

Заранее спасибо.


person Jerad Rose    schedule 17.03.2011    source источник


Ответы (3)


Вы инициализируете свою единицу работы в конструкторе фильтра действий, что означает, что она будет внедрена при создании экземпляра фильтра действий. Цитата из примечаний к выпуску ASP.NET MVC 3:

В предыдущих версиях ASP.NET MVC фильтры действий создавались для каждого запроса, за исключением нескольких случаев. Это поведение никогда не было гарантированным поведением, а просто деталью реализации, и контракт для фильтров должен был считать их не имеющими состояния. В ASP.NET MVC 3 фильтры кэшируются более агрессивно. Таким образом, любые настраиваемые фильтры действий, которые неправильно сохраняют состояние экземпляра, могут быть нарушены.

person Darin Dimitrov    schedule 17.03.2011
comment
Спасибо, это именно то, что происходит. Я пытался найти информацию о кэшировании фильтров действий, но так и не наткнулся на это в своих поисках. - person Jerad Rose; 17.03.2011
comment
Хотел бы я проголосовать за это 5 раз. Убийца при обновлении приложений MVC 1/2. - person Paul; 01.05.2013

Убедитесь, что контейнер зависимостей возвращает один и тот же экземпляр во всех местах, и перепишите фильтр, чтобы избежать кэширования состояния:

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

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
    }
}
person Thomas Eyde    schedule 17.03.2011

Я бы проверил время жизни в вашем репозитории. Это, безусловно, было виновником нашей реализации.

person neontapir    schedule 17.03.2011
comment
Я использую TransientLifetimeManager() в своих репозиториях. Мой ObjectContext и UnitOfWork используют пользовательский PerExecutionContextLifetimeManager(), который в основном соответствует времени жизни каждого запроса. Должны ли мои репозитории также быть PerExecutionContextLifetimeManager()? - person Jerad Rose; 17.03.2011
comment
Обновление: я только что попробовал это, просто чтобы исключить это, и использование PerExecutionContextLifetimeManager() также дает те же результаты. Есть ли другие варианты, которые я должен попробовать? - person Jerad Rose; 17.03.2011