Ледаче завантаження проти нетерплячого завантаження


79

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

Буду вдячний, якщо хтось пояснить мені, в якій ситуації нетерпляче завантаження було б вигідніше, ніж ледаче завантаження, і чому ми взагалі використовуємо його, хоча є щось більш зручне для ресурсів, як Ледаче завантаження.


8
Уявіть ситуацію, коли ваш db-контекст був би утилізований, а ліниве завантаження більше не могло відбуватися. Тоді охоче навантаження вигідне.
Трансцендентний

2
Я бачив, що багато проектів зазнають невдач через проблеми з продуктивністю через проблему "N + 1 Select", яка буде виникати швидше при ледачому завантаженні, тому будьте впевнені, що це потрібно шукати
Девід DV

Відповіді:


80

Я вважаю, що добре класифікувати такі відносини

Коли використовувати охоче завантаження

  1. В "одній стороні" відносин "один-до-багатьох", які ви впевнені, що використовуються всюди з основною суттю. як властивість Користувача статті. Властивість категорії продукту.
  2. Як правило, коли відносин не надто багато, і прагнення завантаження буде гарною практикою зменшити подальші запити на сервері.

Коли використовувати ліниве навантаження

  1. Майже на кожній "колекційній стороні" відносин "один-до-багатьох". як статті користувача чи товари категорії
  2. Ви точно знаєте, що вам не знадобиться нерухомість одразу.

Примітка: як Transcendent сказав, що може виникнути проблема утилізації з ледачим завантаженням.


5
Я просто намагався відповісти на те саме. Використовуйте ліниве завантаження, коли знаєте, що рідко потрібно буде використовувати відповідні дані. Але коли ви знаєте, що вам досить часто потрібні будуть певні пов’язані дані, використовуйте охоче завантаження.
Ghasan

чи можу я використовувати обидва разом?, наприклад, якщо сутність майже пов'язана з іншою, я можу включити її за допомогою нетерплячого завантаження, а інші пов'язані сутності будуть за допомогою ледачого завантаження?
Ахмад Алаа

28

Прагне завантаження: Завдання завантаження допомагає завантажувати всі необхідні сутності одночасно. тобто пов'язані об'єкти (дочірні об'єкти) завантажуються автоматично з його батьківським об'єктом.

Коли використовувати:

  1. Використовуйте Eager Loading, коли відносин не надто багато. Таким чином, енергійне завантаження - хороша практика для зменшення подальших запитів на сервері.
  2. Використовуйте енергійне завантаження, коли ви впевнені, що скрізь будете використовувати пов’язані сутності з основною суттю.

Ледаче завантаження: У разі ледачого завантаження пов’язані об’єкти (дочірні об’єкти) не завантажуються автоматично з його батьківським об’єктом, доки вони не запитуються. За замовчуванням LINQ підтримує ліниве завантаження.

Коли використовувати:

  1. Використовуйте «Ледаче завантаження», коли використовуєте колекції «один до багатьох».
  2. Використовуйте «Ледаче завантаження», коли ви впевнені, що не використовуєте пов’язані об’єкти миттєво.

ПРИМІТКА. Entity Framework підтримує три способи завантаження пов’язаних даних - нетерпляче завантаження, ліниве завантаження та явне завантаження.


Мене дуже бентежить нетерпляче та ліниве завантаження. не могли б ви мене зрозуміти, будь ласка! Посилаючись на google, я міг би сказати цю річ про ліниве завантаження. "Ви повинні використовувати віртуальне ключове слово, коли ви хочете завантажувати дані з лінивим завантаженням." Ледаче завантаження "- це процес, при якому сутність або колекція сутностей автоматично завантажуються з бази даних при першому зверненні. 7 січня 2016 р. те саме, що ви сказали про ліниве завантаження.
рикамол

@rykamol Спробуйте зрозуміти це як шаблон дизайну. Ви можете звернутися звідси для кращого розуміння: Нетерпляче завантаження - entityframeworktutorial.net/… , Ледаче завантаження - entityframeworktutorial.net/… , Явне завантаження - entityframeworktutorial.net/EntityFramework4.3/…
Dark Matter

20

Ледаче завантаження призведе до кількох викликів SQL, тоді як завзяте завантаження може завантажувати дані одним "більш важким" викликом (із об'єднаннями / підзапитами).

Наприклад, якщо між вашим веб-сервером і серверами sql є високий пінг, ви б використовували енергійне завантаження замість завантаження пов'язаних елементів 1 на 1 за допомогою ледачого завантаження.


чи можу я використовувати обидва разом?, наприклад, якщо сутність майже пов'язана з іншою, я можу включити її за допомогою нетерплячого завантаження, а інші пов'язані сутності будуть за допомогою ледачого завантаження?
Ахмад Алаа

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 буде жити разом із запитом (у випадку веб-програм).
Miroslav Holec

@MiroslavHolec: Блискуче, це те, що я насправді роблю, використовуючи Ninject. Те, що ви щойно згадали, справді дуже дуже приємне.
Трансцендентний

8

Стрімке завантаження Коли ви впевнені, що хочете отримати кілька об’єктів одночасно, наприклад, вам потрібно показати дані користувача та користувача на тій самій сторінці, тоді вам слід піти з нетерплячим завантаженням. Ретельне завантаження робить одне звернення до бази даних і завантажує відповідні сутності.

Ледаче завантаження Коли вам потрібно показувати користувачів лише на сторінці, і, натискаючи на користувачів, вам потрібно показати дані користувача, тоді вам потрібно піти з лінивим завантаженням. Ледаче завантаження робить кілька звернень, щоб отримати завантаження пов’язаних сутностей під час прив’язки / ітерації пов’язаних сутностей.


2

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

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


-1

Краще використовувати охоче завантаження, коли це можливо, оскільки це оптимізує продуктивність вашого додатка.

екс-:

Eager loading

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

lazy loading

У моделі замовник повинен визначити

Public virtual string membershipType {get; set;}

Отже, при запиті лінивого завантаження набагато повільніше завантажуються всі посилальні об’єкти, але прагне завантаження запиту і вибирається лише той об’єкт, який є релевантним.


скористайтеся інструментами діагностики продуктивності, такими як Glimpse, і перевірте, як працюють обидва, під час ледачого завантаження, маючи кілька підключень, а запити, які прагнуть мати лише одне. Я перевірив їх практично, будь ласка, згадайте, чому ви це неправильно сказали.
Nuwan Dhanushka

#FakeCaleb видалив свій коментар
Nuwan Dhanushka

Мод видалив мій коментар, я не бачив сенсу продовжувати цю розмову, оскільки ти все
одно

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

Я просто вважаю, що завдяки формулюванню ви стверджуєте, що нетерпляче завантаження краще, ніж ледаче завантаження завдяки продуктивності. Я можу думати про сценарії, коли це не відповідає дійсності.
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
Ця відповідь взагалі не стосується питання ОП. ОП не запитує про те, як це зробити Lazy loading, він запитує про те, "коли Lazy loadingі коли використовувати Eager Loading"
Міша
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.