HttpContext в атрибутах MVC - проблемы с потоками? - PullRequest
4 голосов
/ 10 марта 2011

У меня была настройка управления сеансом NHibernate следующим образом:

    protected MvcApplication()
    {
        BeginRequest += delegate
                            {
                                NHibernateSessionManager.Instance.OpenSession();
                             };
        EndRequest += delegate
                            {

                                NHibernateSessionManager.Instance.CloseSession();
                            };
    }

И когда мне нужно было сохранить в базу данных, я создал атрибут ActionFilterAttribute, который выглядел так:

открытый классTransactionAttribute: ActionFilterAttribute {private ITransaction _currentTransaction;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _currentTransaction = NHibernateSessionManager.Instance.CurrentSession.Transaction;
        _currentTransaction.Begin();
    }


    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (_currentTransaction.IsActive)
        {
            if (filterContext.Exception == null)
                _currentTransaction.Commit();
            else
            {
                _currentTransaction.Rollback();
            }
        }
        _currentTransaction.Dispose();
    }
}

, а затем я могу просто добавить [Transaction] в свой метод действия.Похоже, это сработало при первоначальном тестировании, но затем я попытался использовать HttpWebRequest для многократного вызова метода действия из другого приложения, и у меня возникли проблемы.Тестируя с помощью Fiddler, я установил запрос POST, а затем быстро выполнил их, и он обнаружил следующее: WebRequests

Красные - это различные ошибки, которые, как я считаю, связаны с многопоточностью.

Мой NHibernateSessionManager использует HTtpContext для хранения сеанса следующим образом:

    public ISession CurrentSession
    {
        get { return (ISession)HttpContext.Current.Items["current.session"]; }
        set { HttpContext.Current.Items["current.session"] = value; }
    }

Итак, чтобы исправить это, я переместил свой код транзакции в мои методы BeginRequest и EndRequest - и затем я мог запуститьот кучи подряд.

Мой вопрос - почему это исправлено?Я бы подумал, что у меня было бы что-то похожее на это: Begin Request - открывает сеанс OnActionExecuting - запускает код действия транзакции OnActionExecuted - фиксирует транзакцию End Request - закрывает сеанс

и что это будет уникальным для каждого запроса,так что это не должно мешать друг другу, потому что должен быть свой HttpContext для каждого запроса, не так ли?Или они делили что ли ??

Может ли кто-нибудь просветить меня?

1 Ответ

5 голосов
/ 10 марта 2011

Цитата из примечаний к выпуску ASP.NET MVC 3 :

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

Это в основном означает, что экземпляр _currentTransaction, который есть в вашем фильтре действий, может не соответствовать вашему.Так что будьте осторожны, как / когда это свойство вводится => это не ясно из кода, который вы показали.

...