Що робить Include () у LINQ?


93

Я намагався зробити багато досліджень, але я більше хлопець, тому навіть пояснення в MSDN для мене не має ніякого сенсу. Хто-небудь може пояснити і навести кілька прикладів того, що Include()робить твердження в терміні SQLзапиту?


Дуже просто, я знаю лише прості Вибір, Де, Замовлення за деякими сукупними операторами. Я не пробував ПРИЄДНАТИСЯ в LINQ, а також Включити. Моєю кінцевою метою було переписати ці запити LINQ в SQL
CJ

Відповіді:


165

Скажімо, наприклад, ви хочете отримати список усіх своїх клієнтів:

var customers = context.Customers.ToList();

І припустимо, що кожен Customerоб’єкт має посилання на свій набір Orders, і що кожен Orderмає посилання, на LineItemsякі також може посилатися a Product.

Як бачите, вибір об’єкта верхнього рівня із багатьма пов’язаними сутностями може призвести до запиту, який потребує отримання даних із багатьох джерел. Як показник продуктивності Include()дозволяє вказати, які пов’язані об’єкти слід читати з бази даних як частину того самого запиту.

Використовуючи той самий приклад, це може принести всі відповідні заголовки замовлення, але жоден з інших записів:

var customersWithOrderDetail = context.Customers.Include("Orders").ToList();

На завершення після того, як ви попросили SQL, перший оператор без Include()може створити просте твердження:

SELECT * FROM Customers;

Остаточне твердження, яке викликає, Include("Orders")може виглядати так:

SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;

1
Дякую. На вашому прикладі, чи можу я сказати, якщо я хочу також включити LineItemsі Products, запит LINQ повинен виглядати так var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();:?
CJ

2
Так, ви можете зв’язати кілька викликів, Include()щоб захопити об’єкти за різницею «шляхів». Якщо ви хочете об'єкти в одному шляху, вам потрібно зробити лише один виклик, який визначає весь шлях. Оскільки LineItemsі Productsне діляться жодними компонентами шляху, вам потрібні окремі виклики.
Юк

Чи обов’язково використовувати Включити? Я майже впевнений, що працював над рішеннями, де я міг би отримати пов'язані об'єкти, не використовуючи його.
Jepzen

@Jepzen Це залежить від того, використовуєте ви об’єкти, що завантажуються ліниво, чи ні.
Юк

@Yuck, я вважаю, що це працює, коли ви використовуєте ледаче завантаження, у разі нетерплячого завантаження вам не потрібно використовувати оператор "включити", але це однозначно призведе до проблем із продуктивністю. Будь ласка, виправте мене щодо цього.
sam

27

Я просто хотів додати, що "Включити" є частиною нетерплячого завантаження. Це описано в підручнику Microsoft Entity Framework 6. Ось посилання: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the -entity-framework-in-an-asp-net-mvc-application


Витяг із пов’язаної сторінки:

Ось декілька способів, як Entity Framework може завантажувати пов’язані дані у властивості навігації сутності:

Ліниве завантаження. Коли об'єкт читається вперше, пов'язані дані не отримуються. Однак під час першої спроби отримати доступ до властивості навігації дані, необхідні для цього властивості навігації, автоматично отримуються. Це призводить до декількох запитів, надісланих до бази даних - по одному для самої сутності та по одному кожного разу, коли пов'язані дані для сутності повинні бути отримані. Клас DbContext за замовчуванням дозволяє поступове завантаження.

Прагне завантаження. Коли об’єкт читається, разом із ним отримуються відповідні дані. Зазвичай це призводить до одного запиту на приєднання, який отримує всі необхідні дані. Ви визначаєте нетерпляче завантаження за допомогою Includeметоду.

Явне завантаження. Це схоже на ліниве завантаження, за винятком того, що ви явно отримуєте відповідні дані в коді; це не відбувається автоматично, коли ви отримуєте доступ до властивості навігації. Ви завантажуєте пов’язані дані вручну, отримуючи запис об’єкта диспетчера стану для сутності та викликаючи метод Collection.Load для колекцій або метод Reference.Load для властивостей, які містять одну сутність. (У наступному прикладі, якщо ви хочете завантажити властивість навігації адміністратора, ви заміните Collection(x => x.Courses)наReference(x => x.Administrator) .) Зазвичай ви використовуєте явне завантаження лише тоді, коли ви вимкнули ліниве завантаження.

Оскільки вони не відразу отримують значення властивостей, ліниве завантаження та явне завантаження також відомі як відкладене завантаження.


3
Ласкаво просимо до SO =) Просто пропозиція, але коли ви відповідаєте на щось подібне, якщо можете, додайте фрагмент коду. На жаль, посилання можуть загинути.
The_Cthulhu_Kid

2

Подумайте про це як про примусове завантаження в сценарії, коли в під-елементах було б ліниве завантаження.

Надсилання запиту EF до бази даних спочатку дасть більший результат, але при доступі не буде зроблено подальших запитів при доступі до включених елементів.

З іншого боку, без цього EF виконував би окремі запити пізніше, коли ви вперше отримали доступ до підпунктів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.