Размещается ли HttpContext.Current, даже если выдается исключение? - PullRequest
3 голосов
/ 18 июля 2009

Причина, по которой я спрашиваю, состоит в том, что коллекция HttpContext.Current.Items кажется, что было бы хорошим местом для размещения IDisposable объектов, таких как DataContext, чтобы репозиторий мог получить к нему прозрачный доступ без необходимости вставлять какие-либо зависимости, связанные с к конкретной технологии ORM в хранилище. Это также позволило бы хранилищу решить, участвовать ли в UnitOfWork или взять на себя дополнительную ответственность за фактическое сохранение любых изменений.

Например:

Страница:

protected void Page_Load(...)
{
   Items[KeyValueFromConfigurationFile] = new DataContext();
   var repo = new Repository();
   var rootEntity = repo.GetById(1);
}

Репозиторий:

public virtual TEntity GetById(int id)
{
   var ctx = HttpContext.Current.Items[KeyValueFromConfigurationFile] as DataContext;
   return ctx.TEntities.SingleOrDefault(p => p.Id == id);
}

Конечно, я бы проверял наличие нулей и выполнял шаги, необходимые для получения DataContext, если он не был доступен в коллекции HttpContext.Current.Items.

Итак, вернемся к моему первоначальному вопросу, учитывая приведенный выше код: Будет ли HttpContext.Current удален вместе с какими-либо объектами, содержащимися в его коллекции Items, даже если будет сгенерировано исключение?

Ответы [ 2 ]

13 голосов
/ 07 февраля 2011

Объекты в HttpContext.Current.Items не будут удаляться автоматически. Вы должны были бы справиться с этим самостоятельно. Вы можете сделать это в global.asax Application_EndRequest:

            foreach (var item in HttpContext.Current.Items.Values)
            {
                var disposableItem = item as IDisposable;

                if (disposableItem != null)
                {
                    disposableItem.Dispose();
                }
            }
2 голосов
/ 25 сентября 2013

Я не думал, что была проблема с последним сообщением, предоставляющим решение, потому что базовая коллекция не изменяется, что нельзя сделать во время ее перечисления, но я недавно столкнулся со спорадическими ошибками с этим кодом. Мы видели ошибку «Коллекция была изменена; Операция перечисления может не выполняться, когда OnEndRequest запустил и выполнил цикл for ниже:

        foreach (var item in HttpContext.Current.Items.Values)
        {
            var disposableItem = item as IDisposable;

            if (disposableItem != null)
            {
                disposableItem.Dispose();
            }
        }

Таким образом, очевидно, что удаление текущих элементов HttpContext во время итерации коллекции с циклом foreach также может представлять проблему. Есть несколько способов обойти это, но я решил сделать это следующим образом:

        int size = HttpContext.Current.Items.Count;
        if (size > 0)
        {
            var keys = new object[size];
            HttpContext.Current.Items.Keys.CopyTo(keys, 0);

            for (int i = 0; i < size; i++)
            {
                var obj = HttpContext.Current.Items[keys[i]] as IDisposable;
                if (obj != null)
                    obj.Dispose();
            }
        }
...