Ленивая загрузка против нетерпеливой загрузки


79

Ленивая загрузка в Entity Framework - явление по умолчанию, которое происходит при загрузке связанных сущностей и доступе к ним. Однако жадная загрузка относится к практике принудительной загрузки всех этих отношений. Я столкнулся с вопросом, в какой ситуации ускоренная загрузка может быть более выгодной, чем ленивая загрузка. Спрашиваем об этом, потому что очевидно, что ленивая загрузка более дружественна к ресурсам, и даже если мы воспользуемся этим ToList()методом, мы все равно сможем воспользоваться преимуществами ленивой загрузки. Однако я подумал, что, возможно, ленивая загрузка увеличивает количество запросов к реальной базе данных, и, возможно, поэтому иногда разработчики используютInlcudeметод принудительной загрузки всех отношений. Например, при использовании автоматического создания шаблонов Visual Studio в MVC 5 метод Index, который автоматически создается в контроллере, всегда использует нетерпеливую загрузку, и у меня всегда возникал вопрос, почему в этом случае Microsoft использует нетерпеливую загрузку по умолчанию.

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


8
Представьте себе ситуацию, когда ваш контекст db будет удален и ленивая загрузка больше не может выполняться. Тогда жадная загрузка полезна.
Transcendent

2
Я видел, как многие проекты терпят неудачу из-за проблем с производительностью из-за проблемы «N + 1 Select», которая будет возникать быстрее при ленивой загрузке, поэтому обязательно посмотрите это
Дэвид Д.В.

Ответы:


80

Я считаю, что такие отношения можно категоризировать

Когда использовать активную загрузку

  1. На «одной стороне» отношений «один ко многим», которые, как вы уверены, используются повсюду с основным объектом. как пользовательское свойство статьи. Свойство категории продукта.
  2. Обычно, когда отношений не слишком много, и активная загрузка будет хорошей практикой, чтобы уменьшить количество запросов на сервер.

Когда использовать отложенную загрузку

  1. Практически со всех сторон "коллекции" отношений "один ко многим". например статьи пользователя или продукты категории
  2. Вы точно знаете, что недвижимость вам не понадобится сразу.

Примечание: как сказал Transcendent, при ленивой загрузке может возникнуть проблема с удалением.


5
Я просто пытался ответить на то же самое. Используйте отложенную загрузку, если знаете, что связанные данные будут использоваться редко. Но если вы знаете, что вам нужны определенные связанные данные довольно часто, используйте активную загрузку.
Ghasan

Могу ли я использовать оба вместе? Например, если объект почти связан с другим, я могу включить его с помощью активной загрузки, а другие связанные объекты будут с помощью отложенной загрузки?
Ахмад Алаа

28

Жажда загрузки: Жажда загрузки поможет вам загрузить все необходимые объекты сразу. т.е. связанные объекты (дочерние объекты) загружаются автоматически вместе с родительским объектом.

Когда использовать:

  1. Используйте нетерпеливую загрузку, когда отношений не слишком много. Таким образом, нетерпеливая загрузка - это хороший способ уменьшить количество запросов к серверу.
  2. Используйте нетерпеливую загрузку, если вы уверены, что будете везде использовать связанные сущности с основной сущностью.

Ленивая загрузка: в случае отложенной загрузки связанные объекты (дочерние объекты) не загружаются автоматически вместе с родительским объектом, пока они не будут запрошены. По умолчанию LINQ поддерживает отложенную загрузку.

Когда использовать:

  1. Используйте отложенную загрузку при использовании коллекций "один ко многим".
  2. Используйте отложенную загрузку, если вы уверены, что не используете связанные объекты мгновенно.

ПРИМЕЧАНИЕ. Entity Framework поддерживает три способа загрузки связанных данных - активная загрузка, отложенная загрузка и явная загрузка.


Меня действительно смущает нетерпеливая и ленивая загрузка. Не могли бы вы объяснить мне, пожалуйста! По ссылке google я узнал о ленивой загрузке. «Вы должны использовать ключевое слово virtual, когда хотите загружать данные с отложенной загрузкой. Ленивая загрузка - это процесс, при котором сущность или коллекция сущностей автоматически загружается из базы данных при первом доступе к ней. 7 января 2016 г.» - то же самое, что вы сказали о ленивой загрузке.
rykamol

@rykamol Попытайтесь понять это как шаблон проектирования. Для лучшего понимания вы можете обратиться отсюда: Активная загрузка - entityframeworktutorial.net/… , Ленивая загрузка - entityframeworktutorial.net/… , Явная загрузка - entityframeworktutorial.net/EntityFramework4.3/…
Dark Matter

20

Ленивая загрузка приведет к нескольким вызовам SQL, в то время как при нетерпеливой загрузке данные могут быть загружены одним «более тяжелым» вызовом (с соединениями / подзапросами).

Например, если между вашим веб-сервером и сервером sql наблюдается высокий пинг, вы должны использовать «Нетерпеливую» загрузку вместо загрузки связанных элементов по одному с отложенной загрузкой.


Могу ли я использовать оба вместе? Например, если объект почти связан с другим, я могу включить его с помощью активной загрузки, а другие связанные объекты будут с помощью отложенной загрузки?
Ахмад Алаа

12

Рассмотрим ситуацию ниже

public class Person{
    public String Name{get; set;}
    public String Email {get; set;}
    public virtual Employer employer {get; set;}
}

public List<EF.Person> GetPerson(){
    using(EF.DbEntities db = new EF.DbEntities()){
       return db.Person.ToList();
    }
}

Теперь после вызова этого метода вы больше не можете лениво загружать Employerобъект. Почему? потому что dbобъект утилизирован. Так что вам нужно сделать, Person.Include(x=> x.employer)чтобы это было загружено.


3
Да, это пример, когда отложенная загрузка не помогает. Другое дело, что создавать DbContext каждый раз, когда вам понадобятся какие-то данные, - плохой способ. Если у вас какой-то контейнер IoC, ваш DbContext будет жить вместе с Request (в случае веб-приложений).
Мирослав Голец

@MiroslavHolec: Великолепно, именно этим я и занимаюсь с помощью Ninject. То, что вы только что упомянули, действительно очень приятно.
Transcendent

8

Активная загрузка Если вы уверены, что хотите получить одновременно несколько объектов, например, вы должны показать пользователя и его данные на одной странице, тогда вам следует перейти к активной загрузке. При активной загрузке выполняется одноразовое обращение к базе данных и загрузка связанных сущностей.

Ленивая загрузка Когда вам нужно отображать пользователей только на странице, и, щелкая по пользователям, вам нужно отобразить данные пользователя, вам нужно перейти к отложенной загрузке. Ленивая загрузка делает несколько обращений, чтобы загрузить связанные объекты при связывании / итерации связанных объектов.


2

Ленивая загрузка - хороша при обработке с разбивкой на страницы, например, когда на странице появляется список пользователей, который содержит 10 пользователей, и когда пользователь прокручивает страницу вниз, вызов API приводит к следующим 10 пользователям. Это хорошо, когда вы не хотите загружать данные enitire в один раз, так как это займет больше времени и ухудшит пользовательский опыт.

Неторопливая загрузка - это хорошо, как предлагали другие люди, когда нет много связей и сразу извлекает все данные за один вызов базы данных


-1

По возможности лучше использовать активную загрузку, поскольку это оптимизирует производительность вашего приложения.

ex-:

Eager loading

var customers= _context.customers.Include(c=> c.membershipType).Tolist();

lazy loading

В модели заказчик должен определить

Public virtual string membershipType {get; set;}

Таким образом, при запросе ленивая загрузка намного медленнее загружает все ссылочные объекты, но при этом выполняется запрос на загрузку и выбирает только релевантный объект.


используйте инструменты диагностики производительности, такие как Glimpse, и проверьте, как работают оба, в то время как при ленивой загрузке имеется несколько подключений, а запросы - только одно. Я проверил их практически, пожалуйста, укажите, почему вы так ошибаетесь.
Нуван Дханушка

#FakeCaleb удалил свой комментарий
Нуван Дханушка

Мод удалил мой комментарий, я не видел смысла продолжать этот разговор, так как вы все
равно

Вы не упомянули точный момент и сказали, что мой комментарий полностью вводит в заблуждение, если вы укажете, какие пункты неверны, я также могу узнать.
Нуван Дханушка

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

-2
// Using LINQ and just referencing p.Employer will lazy load
// I am not at a computer but I know I have lazy loaded in one
// query with a single query call like below.
List<Person> persons = new List<Person>();
using(MyDbContext dbContext = new MyDbContext())
{
    persons = (
        from p in dbcontext.Persons
        select new Person{
            Name = p.Name,
            Email = p.Email,
            Employer = p.Employer
        }).ToList();
}

1
Хотя этот фрагмент кода может решить вопрос, включение объяснения действительно помогает улучшить качество вашего сообщения. Помните, что вы отвечаете на вопрос читателей в будущем, и эти люди могут не знать причин вашего предложения кода.
He Yifei 何 一 非

1
Этот ответ вообще не касается вопроса OP. OP не спрашивает о том, как это сделать Lazy loading, он спрашивает о том, «когда использовать Lazy loadingи когда Eager Loading»
Миша
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.