Как LINQ откладывает выполнение в операторе using

Представьте, что у меня есть следующее:

private IEnumerable MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      return dc.tablename.Select(row => row.parameter == a);
   }
}

private void UsingFunc()
{
   var result = MyFunc(new a());

   foreach(var row in result)
   {
      //Do something
   }
}

Согласно документации выполнение linq будет отложено до тех пор, пока я не перечислю результат, который появляется в строке на foreach. Однако оператор using должен принудительно собирать объект в конце вызова MyFunct ().

Что на самом деле происходит, когда запускается утилита для удаления и / или результат?

Единственное, о чем я могу думать, это то, что отложенное выполнение вычисляется во время компиляции, поэтому фактический вызов перемещается компилятором в первую строку foreach, в результате чего использование выполняется правильно, но не выполняется до строки foreach? Есть ли гуру, который может помочь?

Обновлено: ПРИМЕЧАНИЕ. Этот код действительно работает, я просто не понимаю, как это сделать.

Я немного прочитал и понял в своем коде, что я вызвал метод расширения ToList (), который, конечно, перечисляет результат. Отмеченный ответ поведение полностью соответствует фактическому ответу на вопрос.

Приносим извинения за путаницу.

хороший вопрос. Я был разбомблен этим .. Использование (DataContext) впечатляюще взрывается

Gishu 19.01.2009 09:52

Я получаю ObjectDisposedException «DataContext доступен после Dispose». когда я попробую это. Ваш MyDataContext - это автоматически созданный DataContext из конструктора LINQ? Наследуется ли он от DataContext?

Cameron MacFarland 19.01.2009 10:44

Я в-третьих, идея: если вы избавляетесь от своего контекста данных, используя "Использование", вы получите исключение времени выполнения, если попытаетесь использовать контекст данных позже. Я знаю, что сделал это.

Amy B 20.01.2009 02:22

Приношу извинения всем, см. Мой обновленный вопрос, вы совершенно правы.

Spence 20.01.2009 08:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
4
2 480
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я ожидал, что это просто не сработает; Select отложен, поэтому на данный момент данные не использовались. Однако, поскольку вы удалили контекст данных (перед тем, как покинуть MyFunc), он никогда не сможет получить данные. Лучшим вариантом является передача контекста данных в методу, чтобы потребитель мог выбрать время жизни. Кроме того, я бы рекомендовал вернуть IQueryable<T>, чтобы потребитель мог «составить» результат (т.е. добавить OrderBy / Skip / Take / Where и т. д. И повлиять на окончательный запрос):

// this could also be an instance method on the data-context
internal static IQueryable<SomeType> MyFunc(
    this MyDataContext dc, parameter a)
{
   return dc.tablename.Where(row => row.parameter == a);
}

private void UsingFunc()
{
    using(MyDataContext dc = new MyDataContext()) {
       var result = dc.MyFunc(new a());

       foreach(var row in result)
       {
           //Do something
       }
    }
}

Обновление: если вы (комментарии) не хотите откладывать выполнение (т.е. вы не хотите, чтобы вызывающий абонент имел дело с контекстом данных), вам необходимо оценить результаты. Вы можете сделать это, вызвав .ToList() или .ToArray() для результата для буферизации значений.

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      // or ToList() etc
      return dc.tablename.Where(row => row.parameter == a).ToArray();
   }
}

Если вы хотите оставить его отложенным в этом случае, вам нужно использовать «блок итератора»:

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      foreach(SomeType row in dc
          .tablename.Where(row => row.parameter == a))
      {
        yield return row;
      }
   }
}

Теперь это отложено без передачи контекста данных.

Я пытаюсь исключить операции с базой данных из бизнес-логики, поэтому я стараюсь не передавать текст данных. Все, что мне нужно, это списки, перечисления и скаляры из этих функций.

Spence 19.01.2009 09:45

Будет ли это попадать в базу данных каждый раз? Или он выполнит запрос, а затем вернет каждое значение?

Spence 19.01.2009 10:03

Он попадает в БД, как только возвращается первый результат.

Cameron MacFarland 19.01.2009 10:05

он попадает в дБ каждый год? или ударил по БД один раз, а затем сохранил результаты в памяти?

Spence 19.01.2009 11:40

Он попадает в базу данных один раз за звонящий «foreach» - затем имеет активное соединение в течение для foreach вызывающего абонента; блок итератора гарантирует, что контекст данных закрыт (и, следовательно, соединение закрыто), когда вызывающий foreach завершается. Ничего не буферизуется.

Marc Gravell 19.01.2009 12:38

@Marc: Разве SQL не будет выполняться один раз, а затем буферизироваться для каждого оператора yield?

Cameron MacFarland 20.01.2009 02:01

@Cameron - нет, действительно не будет; не все в буфере; на live-data-context / sql-connection ссылается конечный автомат, созданный компилятором. Один из основных приемов LINQ заключается в том, что он полностью отложен: когда вы выполняете «MoveNext ()» (foreach), он считывает данные из входящего потока TDS (SQL).

Marc Gravell 20.01.2009 09:27

Даже если DataReader удерживается для повторения, SQL все равно выполняется один раз.

Amy B 20.01.2009 20:40

Если я вызываю MyFunc (1) .Take (1) .ToList () и там две строки, не удаляется ли DataContext должным образом?

Amy B 21.10.2010 22:27

@David - ортогонален утилизации; бит это не повлияет на это - просто потребляется только одна запись. итераторы все еще расположены должным образом, благодаря (отчасти) тому, как определен "foreach".

Marc Gravell 21.10.2010 22:36

Я думаю, что есть пробел в моем понимании использования / finally в этих методах итератора. Спасибо, что помог мне закрыть его.

Amy B 21.10.2010 22:42

Я только что опубликовал еще одно решение для этой проблемы здесь с отложенным выполнением, включая этот пример кода:

IQueryable<MyType> MyFunc(string myValue)
{
    return from dc in new MyDataContext().Use()
           from row in dc.MyTable
           where row.MyField == myValue
           select row;
}

void UsingFunc()
{
    var result = MyFunc("MyValue").OrderBy(row => row.SortOrder);
    foreach(var row in result)
    {
        //Do something
    }
}

Метод расширения Use() по существу действует как отложенный блок using.

Я уже принял ответ, но это действительно отличный способ мышления. .Use () метод расширения. Вы заслуживаете большего, чем +1 за такой ответ.

Spence 24.07.2009 02:44

Дополнительный веб-сайт для тех из вас, кому нравится «MyDataContext (). Use ()» ?! lostechies.com/keithdahlby/2009/07/23/…

Meadock 23.08.2019 18:16

Другие вопросы по теме