Ваше описание (1) является верным, но оно является примером «Стремительной загрузки», а не «отложенной загрузки».
Ваше описание (2) неверно.(2) технически вообще не использует загрузку, но будет использовать отложенную загрузку, если вы попытаетесь получить доступ к каким-либо нескалярным значениям на ваших FlaggedDates.
В любом случае вы правы, что никакие данные не будут загружены изваше хранилище данных, пока вы не попытаетесь «сделать что-то» с _flaggedDates.Однако в каждом случае происходит по-разному.
(1): Стремительная загрузка: как только вы начнете цикл for
, каждый из указанных вами объектов будет извлечен из базы данных ивстроенный в гигантскую структуру данных в памяти.Это будет очень дорогая операция, которая потребует огромное количество данных из вашей базы данных.Однако все это произойдет за один прием в одну и ту же базу данных, и будет выполнен один запрос SQL.
(2): отложенная загрузка: когда начинается цикл for
, он загружает только объекты FlaggedDates.Однако, если вы обращаетесь к связанным объектам внутри цикла for
, эти объекты еще не будут загружены в память.Первая попытка получить запланированные школы для заданной даты FlaggedDate приведет либо к отправке туда и обратно новой базы данных, либо к исключению, потому что ваш контекст уже удален.Поскольку вы будете получать доступ к коллекции scheduleSchools в цикле for
, у вас будет новая база данных в оба конца для каждой FlaggedDate, которую вы изначально загрузили в начале цикла for
.
Ответ на комментарии
Отключение отложенной загрузки - это не то же самое, что включение активной загрузки.В этом примере:
context.ContextOptions.LazyLoadingEnabled = false;
var schools = context.FlaggedDates.First().scheduledSchools;
Переменная schools
будет содержать пустую коллекцию EntityCollection, потому что я не Include
их в исходном запросе (FlaggedDates.First ()), и я отключил отложенную загрузкучтобы они не могли быть загружены после выполнения исходного запроса.
Вы правы, что where d.dateID == 2
будет означать, что будут извлечены только объекты, связанные с этим конкретным объектом FlaggedDate. Однако, в зависимости отна том, сколько объектов связано с этим FlaggedDate, вы все равно можете получить много данных, передаваемых по этому проводу.Это связано с тем, как EntityFramework создает свой SQL-запрос.Результаты SQL-запросов всегда представлены в табличном формате, то есть для каждой строки должно быть одинаковое количество столбцов.Для каждого запланированного объекта должна быть как минимум одна строка в наборе результатов, и, поскольку каждая строка должна содержать не менее некоторое значение для каждого столбца, вы получите каждое скалярное значение в вашем объекте FlaggedDateповторяетсяПоэтому, если у вас есть 10 запланированных школ и 10 интервью, связанных с вашей FlaggedDate, у вас будет 20 строк, каждая из которых содержит каждое скалярное значение в FlaggedDate.Половина строк будет иметь значения NULL для всех столбцов ScheduledSchool, а другая половина будет иметь значения NULL для всех столбцов Interviews.
Однако в этом случае все становится очень плохо, если вы углубляетесь.в данных, которые вы включаете.Например, если у каждого ScheduledSchool есть свойство students
, которое вы также включили, то вдруг у вас будет строка для каждого ученика в каждом ScheduledSchool, и в каждой из этих строк будет включено каждое скалярное значение для ScheduledSchool студента(даже если в конечном итоге используются только значения первой строки), вместе с каждым скалярным значением исходного объекта FlaggedDate.Это может сложиться быстро.
Трудно объяснить в письменной форме, но если вы посмотрите на фактические данные, возвращающиеся из запроса с несколькими Include
с, вы увидите, что есть много дублирующих данных,Вы можете использовать LinqPad для просмотра SQL-запросов, сгенерированных вашим EF-кодом.