Я пытался сделать много исследований, но я больше парень из db, поэтому даже объяснение в MSDN не имеет для меня никакого смысла. Может ли кто-нибудь объяснить это и предоставить несколько примеров того, что делает оператор Include()
в терминах запроса SQL
?
Что делает Include() в LINQ?
Ответ 1
Скажем, например, вы хотите получить список всех ваших клиентов:
var customers = context.Customers.ToList();
И пусть предположим, что каждый объект Customer
имеет ссылку на свой набор Orders
и что каждый Order
имеет ссылки на LineItems
, который также может ссылаться на 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;
Ответ 2
Я просто хотел добавить, что "Include" является частью активной загрузки. Он описан в учебнике Entity Framework 6 от Microsoft. Ссылка здесь: 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 может загружать связанные данные в свойства навигации объекта:
Lazy loading. Когда объект сначала считывается, связанные данные не извлекаются. Однако при первом попытке доступа к свойствам навигации данные, необходимые для этого свойства навигации, автоматически извлекаются. Это приводит к нескольким запросам, отправленным в базу данных - по одному для самой сущности и по одному, когда необходимо получить связанные данные для объекта. Класс DbContext позволяет по умолчанию выполнять ленивую загрузку.
Желаемая загрузка. Когда объект считывается, вместе с ним извлекаются связанные данные. Обычно это приводит к одному запросу соединения, который извлекает все необходимые данные. Вы указываете загрузку с помощью метода
Include
.Явная загрузка.. Это похоже на ленивую загрузку, за исключением того, что вы явно извлекаете связанные данные в код; это не происходит автоматически при доступе к навигационному свойству. Вы вручную загружаете связанные данные, получая запись менеджера состояний объекта для объекта и вызывая метод Collection.Load для коллекций или метод Reference.Load для свойств, содержащих один объект. (В следующем примере, если вы хотите загрузить свойство навигации администратора, замените
Collection(x => x.Courses)
наReference(x => x.Administrator)
.) Обычно вы используете явную загрузку только тогда, когда вы отключаете ленивую загрузку.Поскольку они не сразу извлекают значения свойств, ленивая загрузка и явная загрузка также известны как отложенная загрузка.
Ответ 3
Подумайте об этом как о принудительном загрузке в сценарии, в котором ваши подпозиции в противном случае были бы ленивыми.
Запрос EF, отправляемый в базу данных, сначала даст больший результат, но при доступе последующие запросы не будут выполняться при доступе к включенным элементам.
С другой стороны, без него EF будет выполнять separte-запросы позже, когда вы сначала получите доступ к подпозициям.