Почему можно перечислить запрос DBLINQ после вызова DataContext?
Вопрос
Обновлять - Очевидно, что Длинк не реализует Dispose()
должным образом. Ох!
Ниже приведен все вводит вводящий в заблуждение - нижняя строка: DBLINQ нет (пока) эквивалентно LinqtoSQL, как я предполагал, когда я первоначально задавал этот вопрос. Используйте это с осторожностью!
Я использую шаблон репозитория с ДЛИНВ. Мои объекты репозитория реализуют IDisposable
, и то Dispose()
Метод делает только вещь - звонки Dispose()
на DataContext
. Отказ Всякий раз, когда я использую репозиторий, я обертую его в using
Блок, как это:
public IEnumerable<Person> SelectPersons()
{
using (var repository = _repositorySource.GetPersonRepository())
{
return repository.GetAll(); // returns DataContext.Person as an IQueryable<Person>
}
}
Этот метод возвращает IEnumerable<Person>
, Так что, если мое понимание верно, никакого запроса базы данных фактически происходит до Enumerable<Person>
пересекается (например, путем преобразования его в список или массив или используя его в foreach
Цикл), как в этом примере:
var persons = gateway.SelectPersons();
// Dispose() is fired here
var personViewModels = (
from b in persons
select new PersonViewModel
{
Id = b.Id,
Name = b.Name,
Age = b.Age,
OrdersCount = b.Order.Count()
}).ToList(); // executes queries
В этом примере, Dispose()
вызывается сразу после настройки persons
, что является IEnumerable<Person>
, И это единственный раз, когда он призывает.
Итак, три вопроса:
- Как это работает? Как можно утилизировать
DataContext
все еще запроси база данных для результатов послеDataContext
был утилизирован? - Что значит
Dispose()
на самом деле делать? - Я слышал, что это не нужно (например, см. этот вопрос) распоряжаться
DataContext
, Но мое впечатление было то, что это неплохая идея. есть ли смысл нет Утилизировать дблинкDataContext
?
Решение
1 Как эта работа? Как распоряжена распоряженным DataContext по-прежнему запросит базу данных для результатов после распоряжения DataContext?
Это нет Работа. Есть что-то, что вы не показываете нам. Я предполагаю, что либо ваш класс репозитория не распоряжается DataContext
правильно / в нужное время, или что вы небрежные письма ToList()
В конце каждого запроса, который полностью отрицает преобразование запроса и отсроченное исполнение, которое вы обычно получаете.
Попробуйте следующий код в тестовом приложении, я гарантия ты что это бросит ObjectDisposedException
:
// Bad code; do not use, will throw exception.
IEnumerable<Person> people;
using (var context = new TestDataContext())
{
people = context.Person;
}
foreach (Person p in people)
{
Console.WriteLine(p.ID);
}
Это самый простой возможный воспроизводимый случай, и он всегда будет бросать. С другой стороны, если вы пишете people = context.Person.ToList()
вместо этого, то результаты запросов уже перечислены внутри то using
Блок, который смогу поспорить, это то, что происходит в вашем случае.
2 Что делает утилизацию () на самом деле?
Среди прочего, он устанавливает флаг, указывающий, что DataContext
расположено, что проверяется на каждом последующем запросе и вызывает DataContext
бросать ObjectDisposedException
с сообщением Object name: 'DataContext accessed after Dispose.'.
Это также закрывает соединение, если DataContext
открыл его и оставил его открытым.
3 Я слышал, что не нужно (например, см. Этот вопрос) для утилизации DataContext, но мое впечатление было то, что это неплохая идея. Есть ли какие-либо причина не распоряжаться NinqtoSQL DataContext?
Это является необходимо Dispose
то DataContext
, как это необходимо Dispose
каждый второй IDisposable
. Отказ Вы можете потенциально указывать соединения, если вы не сможете распоряжаться DataContext
. Отказ Вы также можете утерить память, если какая-либо из объектов извлечена из DataContext
хранятся в живых, так как контекст поддерживает внутреннюю идентификационную кэш для модуля рабочего шаблона, который он реализует. Но даже если ничто из этого не было, Это не ваша забота что за Dispose
Метод делает внутренне. Предположим, что это делает что-то важное.
IDisposable
это договор Что говорит: «Очистка не может быть автоматической; вам нужно утилизировать меня, когда вы закончите». У вас нет гарантий того, есть ли объект свой финализатор, который убирает после вас, если вы забудете Dispose
. Отказ Реализации могут быть изменены, поэтому не очень хорошая идея полагаться на наблюдаемое поведение в отличие от явных спецификаций.
Худшее, что может случиться, если вы утили IDisposable
с пустым Dispose
Метод заключается в том, что вы тратите несколько циклов ЦП. Худшее, что может случиться, если вы неудача Утилизировать АН IDisposable
с А. нетривиальная реализация Это то, что вы утечки ресурсов. Выбор здесь очевиден; Если вы видите IDisposable
, Не забудьте ее распоряжаться.
Другие советы
«Лица» - это коллекция Ienumerable, DataContext (репозиторий) требуется только для создания вызова .getnew.
Ключевые слова из / select / etc - это синтаксический сахар для методов расширения, добавляемых в пространстве имен System.linq. Эти методы расширения добавляют функциональность IENumerableable, вы используете в вашем запросе, а не на DataContext. На самом деле, вы можете сделать все это без использования Linq2SQL, программически создавая iEnumerable для демонстрации.
Если вы пытаетесь сделать любые дополнительные репозиторий (DataContext), используя эти объекты, это когда вы получите ошибку.
Коллекция IENumerable будет содержать все записи из вашего репозитория, поэтому вы не требуете DataContext, чтобы сделать запрос.
Методы расширения: http://msdn.microsoft.com/en-us/library/bb383977.aspx.
Методы расширения LINQ:http://msdn.microsoft.com/en-us/library/system.linq.enumerable_members.aspx.
Глубоко внутри API вы, вероятно, увидите метод, используя API, как этот:
http://msdn.microsoft.com/en-us/library/y6wy5a0f(v=vs.100 ).aspx.
Когда команда выполнена, связанное объект подключения закрывается, когда связанный объект DataReader закрыт.