присоединение linq к sql datacontext к httpcontext на бизнес-уровне - PullRequest
6 голосов
/ 20 марта 2010

Мне нужно, чтобы мой текстовый текст 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 ]

8 голосов
/ 22 марта 2010

То, что вы представляете, имеет смысл - использование контекста 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 недавно написал соответствующий пост по этой теме , описывая то, что вы хотите сделать в качестве шаблона, другими словами, способ делать то, что должно повторяться. Он предоставляет класс, чтобы помочь с этим, лениво загрузить контекст БД и перенести его в текущий контекст. Есть некоторые подводные камни с подходом - вы можете прочитать о них в комментариях к дискуссии на этот пост. Также в комментариях цитируется куча связанных статей.

3 голосов
/ 02 июня 2013

Код 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;
        }
    }
}
...