Interfejsy IEnumerable oraz IQueryable mogą wydawać się bardzo podobne. W końcu IQueryable implementuje IEnumerable więc funkcjonalność musi być podobna. W praktyce poniższe dwa zapytania bardzo się różnią:
IEnumerable<Customer> customers = context.Customers.Where(c => c.FirstName.StartsWith("J")); customers = customers.Take<Customers>(5);
IQueryable<Customer> customers = context.Customers.Where(c => c.FirstName.StartsWith("J")); customers = customers.Take<Customers>(5);
Pierwsze zapytanie jest skrajnie niewydajne. Najpierw zostaną wybrani wszyscy klienci z imieniem zaczynającym się od litery J a dopiero potem lokalnie zostanie zwróconych pierwszych 5 wierszy. Jeśli zatem tabela zawiera milion wierszy to wszystkie te wiersze zostaną odczytane z bazy danych. W SQL wyglądałoby to następująco:
select * from Customers WHERE FirstName like 'j%';
W pamięci powstanie tablica zawierająca milion elementów. Następnie metoda Take zwróci pierwszych 5 elementów.
W przypadku interfejsu IQueryable zapytanie wygląda juz w pełni optymalnie tzn:
select top(5) * from Customers WHERE FirstName like 'j%';
Należy zwrócić uwagę na top(5) – z bazy danych zostaną odczytane wyłącznie te wiersze, które tak naprawdę chcemy. Z przykładów widać, że bardzo łatwo napisać niewydajny kod. Wszelkie wywołania IEnumerable są wykonywane lokalnie i nie zostaną przetworzone bezpośrednio w zapytanie SQL.
Dodatkowo polecam lekturę posta Olka Polaka na forum CodeGuru: http://codeguru.pl/frmThread.aspx?id=491116.
Dzięki za info – napewno warto o tym wiedzieć 🙂
Dziękować dziękować 🙂
Przykłady iEnumerable i iQuerable są takie same.