Co robi Include () w LINQ?

96

Próbowałem przeprowadzić wiele badań, ale jestem bardziej typem db - więc nawet wyjaśnienie w MSDN nie ma dla mnie żadnego sensu. Czy ktoś może wyjaśnić i podać kilka przykładów, jakie Include()stwierdzenie robi w SQLzapytaniu?

CJ
źródło
Bardzo podstawowe, znam tylko proste opcje Wybierz, Gdzie, Zamów według, niektóre operatory agregacji. Nie próbowałem JOIN w LINQ ani Include. Moim ostatecznym celem było przepisanie tych zapytań LINQ na SQL
CJ

Odpowiedzi:

170

Załóżmy na przykład, że chcesz uzyskać listę wszystkich swoich klientów:

var customers = context.Customers.ToList();

I załóżmy, że każdy Customerobiekt ma odniesienie do swojego zbioru Ordersi że każdy Orderma odniesienia, do LineItemsktórych może również odnosić się plik Product.

Jak widać, wybranie obiektu najwyższego poziomu z wieloma powiązanymi jednostkami może skutkować zapytaniem, które będzie musiało pobrać dane z wielu źródeł. Jako miara wydajności Include()umożliwia wskazanie, które powiązane jednostki powinny być odczytywane z bazy danych w ramach tego samego zapytania.

Korzystając z tego samego przykładu, może to spowodować wprowadzenie wszystkich powiązanych nagłówków zamówień, ale żadnych innych rekordów:

var customersWithOrderDetail = context.Customers.Include("Orders").ToList();

Na koniec, ponieważ poprosiłeś o SQL, pierwsza instrukcja bez Include()może wygenerować prostą instrukcję:

SELECT * FROM Customers;

Końcowe stwierdzenie, które wywołuje, Include("Orders")może wyglądać tak:

SELECT *
FROM Customers JOIN Orders ON Customers.Id = Orders.CustomerId;
Fuj
źródło
1
Dziękuję Ci. Korzystając z twojego przykładu, czy mogę powiedzieć, czy chcę również uwzględnić LineItemsi Products, zapytanie LINQ powinno wyglądać następująco var customersWithOrderDetail = context.Customers.Include("Orders").Include("LineItems").Include("Products").ToList();:?
CJ
2
Tak, możesz łączyć wiele wywołań w Include()celu przechwytywania obiektów wzdłuż różnych „ścieżek”. Jeśli chcesz, aby obiekty znajdowały się na tej samej ścieżce, musisz wykonać tylko jedno wywołanie, które określa całą ścieżkę. Ponieważ LineItemsi Productsnie współdzielą żadnych komponentów ścieżki, potrzebujesz oddzielnych wywołań.
Fuj
Czy użycie Uwzględnij jest obowiązkowe? Jestem prawie pewien, że pracowałem nad rozwiązaniami, w których mógłbym uzyskać powiązane obiekty bez ich używania.
Jepzen
@Jepzen Zależy to od tego, czy używasz encji ładowanych z opóźnieniem, czy nie.
Fuj
@ Yuck, uważam, że to działa, gdy używasz ładowania z opóźnieniem, w przypadku szybkiego ładowania nie musisz używać instrukcji „include”, ale z pewnością spowoduje to problemy z wydajnością. Proszę, popraw mnie w tej sprawie.
sam
27

Chciałem tylko dodać, że „Uwzględnij” jest częścią niecierpliwego ładowania. Jest to opisane w samouczku Entity Framework 6 firmy Microsoft. Oto link: 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


Fragment z połączonej strony:

Oto kilka sposobów, w jakie Entity Framework może ładować powiązane dane do właściwości nawigacji jednostki:

Powolne ładowanie. Gdy jednostka jest odczytywana po raz pierwszy, powiązane dane nie są pobierane. Jednak przy pierwszej próbie uzyskania dostępu do właściwości nawigacji dane wymagane dla tej właściwości nawigacji są pobierane automatycznie. Powoduje to wysłanie wielu zapytań do bazy danych - jednego dla samej jednostki i za każdym razem, gdy trzeba pobrać powiązane dane dla jednostki. Klasa DbContext domyślnie włącza leniwe ładowanie.

Chętne ładowanie. Gdy jednostka jest odczytywana, wraz z nią pobierane są powiązane dane. Zwykle powoduje to pojedyncze zapytanie sprzężenia, które pobiera wszystkie potrzebne dane. Określasz zachłanne ładowanie za pomocą Includemetody.

Jawne ładowanie. Jest to podobne do ładowania z opóźnieniem, z tą różnicą, że jawnie pobierasz powiązane dane w kodzie; nie dzieje się to automatycznie po uzyskaniu dostępu do właściwości nawigacji. Możesz ładować powiązane dane ręcznie, pobierając wpis menedżera stanu obiektu dla jednostki i wywołując metodę Collection.Load dla kolekcji lub metodę Reference.Load dla właściwości, które przechowują pojedynczą jednostkę. (W poniższym przykładzie, jeśli chcesz załadować właściwość nawigacji administratora, zamień Collection(x => x.Courses)ją na Reference(x => x.Administrator).) Zwykle jawne ładowanie będzie używane tylko wtedy, gdy wyłączysz ładowanie z opóźnieniem.

Ponieważ nie pobierają natychmiast wartości właściwości, ładowanie z opóźnieniem i ładowanie jawne są również nazywane ładowaniem odroczonym.

Minoosha
źródło
3
Witamy w SO =) To tylko sugestia, ale kiedy odpowiadasz na coś takiego, jeśli możesz, dołącz fragment kodu. Linki mogą niestety zniknąć.
The_Cthulhu_Kid
2

Potraktuj to jako wymuszanie szybkiego ładowania w scenariuszu, w którym podelementy ładowałyby się leniwie.

Kwerenda EF wysyła do bazy danych na początku przyniesie większy wynik, ale podczas uzyskiwania dostępu nie będą wykonywane żadne dalsze zapytania podczas uzyskiwania dostępu do uwzględnionych elementów.

Z drugiej strony bez tego EF wykonywałby oddzielne zapytania później, kiedy po raz pierwszy uzyskasz dostęp do elementów podrzędnych.

robkrueger
źródło