HttpContext в атрибутах MVC - проблемы с потоками?

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

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

                                NHibernateSessionManager.Instance.CloseSession();
                            };
    }

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

открытый класс TransactionAttribute: ActionFilterAttribute { частный 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();
    }
}

а затем я мог бы просто добавить [Транзакция] к моему методу действия. Это, казалось, работало при первоначальном тестировании, но затем я попытался использовать 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, не так ли? Или они общие или что??

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


person RodH257    schedule 10.03.2011    source источник


Ответы (1)


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

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

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

person Darin Dimitrov    schedule 10.03.2011