2010-03-20 3 views
6

Мне нужен мой linq для sql datacontext, который будет доступен на моем уровне бизнеса/данных для всех моих объектов репозитория для доступа. Однако, поскольку это веб-приложение, я хочу создать и уничтожить его для каждого запроса. Мне интересно, если бы один одиночный класс, который может лениво создать и прикрепить datacontext к текущему HttpContext, будет работать. Мой вопрос: будет ли datacontext автоматически удаляться после завершения запроса? Ниже приведен код, о котором я думаю. Это выполнит мою задачу: иметь потокобезопасный экземпляр datacontext, который лениво доступен и автоматически удаляется, когда запрос заканчивается?с linq to sql datacontext to httpcontext в бизнес-слое

public class SingletonDC 
{ 
    public static NorthwindDataContext Default 
    { 
     get 
     { 
      NorthwindDataContext defaultInstance = (NorthwindDataContext)System.Web.HttpContext.Current.Items["datacontext"]; 
      if (defaultInstance == null) 
      { 
       defaultInstance = new NorthwindDataContext(); 
       System.Web.HttpContext.Current.Items.Add("datacontext", defaultInstance); 
      } 
      return defaultInstance; 
     } 
    } 
} 

ответ

8

Что вы себе представить, имеет смысл - используя контекст запроса HTTP для хранения вещей - но Нет, одноразовые предметы, хранящиеся в текущем HttpContext будет автоматически не волшебно утилизироваться, когда запрос заканчивается. Так или иначе, вам придется это сделать.

Существует событие «Запрос на завершение», которое можно легко подключить, например, используя код, который вы указываете в Global.asax.cs. В вашем методе Application_EndRequest() вы можете вызвать Dispose() вручную для каждого объекта в требуемом ему списке.

Один из способов сделать это - перебирать каждый элемент в контексте, тестировать IDisposable и затем вызывать Dispose при необходимости.

protected void Application_EndRequest(Object sender, EventArgs e) 
{ 
    foreach (var key in HttpContext.Current.Items.Keys) 
    { 
     var disposable = HttpContext.Current.Items[key] as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
      HttpContext.Current.Items[key] = null; 
     } 
    } 
} 

Я думаю, что это должно быть сделано. ASPNET не делает это для вас автоматически. Конечно, вам нужна защита от исключений и т. Д., Прежде чем использовать этот код в реальном приложении.


Кит Крэйг Головокружения написал a relevant post on the topic a while ago, описывая то, что вы хотите сделать, как шаблон, другими словами, способ делать вещи, которые должны быть повторены. Он предоставляет класс, чтобы помочь с этим, ленить загрузку контекста БД и передать его в текущий контекст. Есть некоторые подводные камни с подходом - вы можете прочитать о них в обсуждении комментария на этом посту. Также есть куча связанных статей, цитируемых в комментариях.

3

Код Cheeso будет генерировать InvalidOperationException"Collection was modified; enumeration operation may not execute", потому что он пытается изменить элементы HttpContext, которые он перебирает.

Чтобы предотвратить это, вы можете использовать копию списка.

protected void Application_EndRequest(Object sender, EventArgs e) 
{ 
    var keys = new ArrayList(HttpContext.Current.Items.Keys); 

    foreach (var key in keys) 
    { 
     var disposable = HttpContext.Current.Items[key] as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
      HttpContext.Current.Items[key] = null; 
     } 
    } 
} 
Смежные вопросы