Почему можно перечислить запрос DBLINQ после вызова DataContext?

StackOverflow https://stackoverflow.com/questions/2851755

  •  27-09-2019
  •  | 
  •  

Вопрос

Обновлять - Очевидно, что Длинк не реализует 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>, И это единственный раз, когда он призывает.

Итак, три вопроса:

  1. Как это работает? Как можно утилизировать DataContext все еще запроси база данных для результатов после DataContext был утилизирован?
  2. Что значит Dispose() на самом деле делать?
  3. Я слышал, что это не нужно (например, см. этот вопрос) распоряжаться 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 закрыт.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top