Доступ К DataContext После Dispose
Я использую ASP.NET 4.0.
у меня есть следующий код, который возвращает с ошибкой "не удается получить доступ к ликвидированному объекту. Имя объекта: 'DataContext доступ после Dispose.'."
public IEnumerable<BatchHeader> GetHeaders()
{
using(NSFChecksDataContext context = DataContext)
{
IEnumerable<BatchHeader> headers = (from h in context.BatchHeaders
select h);
return headers;
}
}
Если я изменю это на:
public IEnumerable<BatchHeader> GetHeaders()
{
using(NSFChecksDataContext context = DataContext)
{
return context.BatchHeaders.ToList();
}
}
Он будет работать нормально. Я использую этот метод для заполнения RadGrid. Может ли кто-нибудь объяснить, почему второй метод будет работать, но не первый?
спасибо.
3 ответов
первый не работает, потому что, когда метод возвращает контекст данных создается в папке using
блок утилизируется. Однако IEnumerable<BatchHeader>
returned лениво оценивается и нуждается в этом контексте данных, чтобы быть живым, чтобы перечислить его результаты.
вы могли бы сделать что-то вроде этого:
public IEnumerable<BatchHeader> GetHeaders() {
using(NSFChecksDataContext context = DataContext) {
foreach(var header in context.BatchHeaders) {
yield return header;
}
}
}
второй блок работает, потому что результаты запроса перечисляются и хранятся в памяти до удаления контекста данных. После этого контекст данных не будет больше не нужна. Однако будьте осторожны при использовании кода, такого как ваш второй блок; если BatchHeaders
таблица очень большая, вы просто вытащили все это в памяти.
теперь, и вот самая серьезная часть моего ответа:Я абсолютно не могу видеть запросы, которые создают контексты данных для выполнения. Я хочу знать и контролировать, когда используются мои контексты данных.
Я предполагаю, что IEnumerable из вашего контекста использует отложенное выполнение, поэтому, если вы не заставляете его перечислять с помощью ToList, он не делает этого, пока вы не используете значения, которые в этом случае находятся вне блока using, поэтому объект будет удален.
return headers.AsEnumerable();
должен работать, потому что по умолчанию запрос linq возвращает объект IQueryable, что означает, что данные не извлекаются из БД до перечисления с помощью foreach, ToArray, ToList или AsEnumerable. Когда Asp.Net пытался получить доступ к IQueryable и получить данные с помощью foreach, соединение уже было закрыто.