Присоединение 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;
}
}
}