3

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

Например:

страницу:

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 вместе с любыми объектами, содержащимися в его коллекции элементов, даже если выбрано исключение?

ответ

13

Объекты в 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(); 
       } 
      } 
+1

Спасибо, это работает. Стоит отметить, как часто запускается EndRequest. В этой теме http://www.mojoportal.com/Forums/Thread.aspx?pageid=5&t=1558~-1. Веб-сервер Visual Studio запускает это событие для всех HTTP-запросов (включая изображения, css и т. Д.), Тогда как IIS запускается только во время обработанных страниц .NET. Имейте это в виду, если вы выполняете отладку на VS Web Server, и вы видите, что событие запускается снова и снова. –

+0

'foreach (var v in HttpContext.Current.Items.Values.OfType ()) v.Dispose();' – Denis

2

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

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

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

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

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

Это правильно, так как коллекция изменяется, и я не уверен в причине. Как правило, вызов dispose не должен влиять на сбор. Возможно, какой-то другой поток изменяет коллекцию одновременно (Application_EndRequest запускается в другом потоке, чем Application_BeginRequest, и после/одновременно с временем отправки ответа клиенту) – Cosmin