Entity Framework - в чем разница между включением / быстрой загрузкой и отложенной загрузкой? - PullRequest
18 голосов
/ 17 августа 2010

Я пытался ознакомиться с Entity Framework.Большая часть этого кажется простой, но я немного запутался в разнице между энергичной загрузкой с помощью метода Include и отложенной загрузкой по умолчанию.Кажется, что оба загружают связанные объекты, поэтому на первый взгляд кажется, что они делают одно и то же.Чего мне не хватает?

Ответы [ 4 ]

30 голосов
/ 17 августа 2010

Допустим, у вас есть две сущности с отношением один-ко-многим: Клиент и Заказ, где у каждого Клиента может быть несколько заказов.

При загрузке сущности Клиента Entity Framework позволяет вам либо стремитьсязагрузить или лениво загрузить коллекцию заказов клиента.Если вы решите загружать коллекцию заказов, то при извлечении клиента из базы данных Entity Framework сгенерирует SQL, который извлекает и информацию о клиенте и заказы клиента в одном запросе.Однако, если вы решите лениво загрузить коллекцию Orders, при извлечении Customer из базы данных Entity Framework сгенерирует SQL, который only извлекает информацию о Customer (Entity Framework затем сгенерирует отдельный оператор SQL, если выполучите доступ к коллекции заказов клиентов позже в своем коде).

Определение того, когда использовать загрузку с нетерпением, а когда - с отложенной загрузкой, все сводится к тому, что вы ожидаете сделать с объектами, которые вы получите.Если вы знаете, что вам нужна только информация о Клиенте, вам следует лениво загрузить коллекцию «Заказы» (чтобы SQL-запрос мог быть эффективен только при получении информации о Клиенте).И наоборот, если вы знаете, что вам нужно пройти через Заказы Клиента, вам следует загружать Заказы с нетерпением (таким образом, вы сэкономите дополнительный удар по базе данных, как только получите доступ к Заказам Клиента в своем коде).

PS Будьте очень осторожны при использовании отложенной загрузки, так как это может привести к проблеме N + 1.Например, предположим, у вас есть страница, которая отображает список клиентов и их заказов.Тем не менее, вы решаете использовать отложенную загрузку при получении заказов.Когда вы выполняете итерацию по коллекции «Клиенты», а затем по каждому «Заказу клиента», вы выполняете обращение к базе данных, чтобы каждый клиент «лениво» загружал свою коллекцию «Заказы».Это означает, что для N клиентов у вас будет N + 1 попадание в базу данных (1 попадание в базу данных для загрузки всех клиентов, затем N попаданий в базу данных для загрузки каждого из их заказов) вместо одного обращения в базу данных, если вы использовали энергичную загрузку(что позволило бы получить все клиенты и их заказы в одном запросе).

17 голосов
/ 11 ноября 2010

Если вы пришли из мира SQL, подумайте о JOIN.

Если вам нужно показать в сетке 10 заказов и клиент, который разместил заказ, у вас есть 2 варианта:

1) LAZY LOAD (= 11 запросов = МЕДЛЕННЫЕ ХАРАКТЕРИСТИКИ)

EF выполнит запрос для получения заказов и запрос для каждого заказа для получения данных о клиентах.

Select * from order where order=1
+
10 x (Select * from customer where id = (order.customerId))

1) НАГРУЗКА EAGER (= 1 запрос = ВЫСОКАЯ ЭФФЕКТИВНОСТЬ)

EF выполнит один запрос для получения заказов и клиентов с помощью JOIN.

Select * from orders INNER JOIN customers on orders.customerId=customer.Id where order=1

PS: Когда вы извлекаете объект из базы данных, объект сохраняется в кэше, когда контекст активен. В примере, который я сделал с LAZY LOAD, , если все 10 заказов относятся к одному и тому же клиенту , вы увидите только 2 запроса, потому что, когда вы просите EF получить объект, EF проверит, является ли объект в кеше, и если он найдет, он не будет запускать еще один SQL-запрос к БД.

6 голосов
/ 17 августа 2010

Стремительная загрузка предназначена для решения проблемы N + 1 Selects , характерной для ORM.Краткая версия такова: если вы собираетесь напрямую получить некоторое количество сущностей и знаете, что будете получать доступ к определенным связанным сущностям через извлеченные сущности, это будет намного более эффективным для извлечения всех связанных сущностей-front за один проход, по сравнению с извлечением их постепенно с помощью отложенной загрузки.

0 голосов
/ 28 марта 2018

Важной проблемой является сериализация.Microsoft рекомендует НЕ использовать ленивую загрузку по умолчанию, если вы имеете дело с сериализованными объектами.Сериализация приводит к вызову ВСЕХ связанных свойств, которые могут запустить цепную реакцию запрашиваемых связанных объектов.Это действительно вступает в игру, если вы возвращаете данные JSON из контроллера.Данные JSON явно сериализованы.Вы либо захотите немедленно вернуть данные через Eager, либо отключите отложенную загрузку в контексте и примените явную отложенную загрузку.

...