Lazy Loading w asp.net mvc - co to jest?

Chciałbym aby ktoś mi swoimi słowami wytłumaczył czym jest LAZY LOADING i kiedy jest on dobry, a kiedy zły? (ja akurat pisze w asp.net mvc). Przeczytałem już trochę informacji na ten temat i jako takie wyrobiłem sobie o tym zdanie i wiedze, ale lubie jak ktoś tłumaczy pewne zagadnienie po swojemu żebym miał jakiś punkt odniesienia.

Reasumując chciałbym uzyskać odpowiedź na te pytania (swoimi słowami, przykładem, a nie w stylu “poszukaj w google”)

1. Czym jest lazy loading?

this.Configuration.LazyLoadingEnabled = false;

.

Piszesz zapytanie do danych w jednym miejscu, a zostanie ono wykonane dopiero w momencie kiedy będziesz tych danych potrzebował.

var dane = (from d in db.DaneSet .. select ... ); // tu się nie wykonuje

// dużo kodu .. 

foreach(var dana in dane) // dopiero tu się faktycznie odwołujez i tu się wykona
{

}

Gdybyś od razu na zapytania wział coś co wymaga zmaterializowania, np.:

var dane = (from d in db.DaneSet .. select ... ).ToList();

… to by się od razu wykonało.

Koncepcja jest uniwersalna. Nie jest związana bezpośrednio z ASP.NET MVC. Generalnie chodzi o to, żeby ładować dane najpóźniej jak się da. Zaleta jest taka, że nie ładujemy danych niepotrzebnie, kiedy np. w wyniku jakiegoś if’a okaże się że ich nie używamy. Wadą, że zachowanie programu może być nieco bardziej niedeterministyczne. Trudniej też taki program się np. debuguje, bo załadowanie danych może nastąpić w zupełnie innym miejscu niż zapytanie.

Przez zapytanie program Ci przeskoczy, a nagle będzie wisieć w zupełnie dziwnym miejscu bo przechodząc przez kilka powiązań coś nie zostało załadowane. Łatwiej nad tym zapanować jeśli ładuje się od razu tam gdzie masz zapytanie.

Czy gdybym zdebugował to

var dane = (from d in db.DaneSet .. select ... ); // tu się nie wykonuje

i postawił brakepointa po zmiennej “dane” to mialbym nulla w tej zmiennej “dane”?

Miałbyś IEnumerable anonimowej klasy z informacją “collection cannot be enumerated”.

Łatwo to sprawdzić. Nie wymaga bazy danych, np:

using System;
using System.Linq;

namespace ConsoleApplication4
{
    class Person
    {
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Person[] people = {
                new Person() { Name = "P1" },
                new Person() { Name = "P2" },
                new Person() { Name = "P3" }
            };

            var queryPeople = (from p in people
                               where p.Name.StartsWith("P")
                               select p); // nie ma danych
            // lub people.Where(p = p.Name.StartsWith("P"))

            var queryPeopleAsList = (from p in people
                                     where p.Name.StartsWith("P")
                                     select p).ToList(); // TU JUŻ BĘDĄ DANE

            int x = 123, y = 1;
            while (y x) { y++; }

            foreach(Person p in people)
            {
                Console.WriteLine(p.Name);
            }
        }
    }
}