Присоединение linq к sql datacontext к httpcontext на бизнес-уровне

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

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;
        }
    }
}

2 ответа

Решение

То, что вы представляете, имеет смысл - использование контекста 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 не делает это для вас автоматически. Конечно, вам нужна защита от исключений и так далее, прежде чем использовать этот код в реальном приложении.


Некоторое время назад Кейт Крейг из Vertigo написал соответствующий пост на эту тему, описывая то, что вы хотите сделать в качестве шаблона, другими словами, способ делать то, что следует повторить. Он предоставляет класс, чтобы помочь с этим, лениво загрузить контекст БД и перенести его в текущий контекст. Есть некоторые подводные камни с подходом - вы можете прочитать о них в комментариях к обсуждению этого поста. Также в комментариях цитируется куча связанных статей.

Код 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;
        }
    }
}
Другие вопросы по тегам