Paweł Łukasiewicz
2015-12-03
Paweł Łukasiewicz
2015-12-03
Udostępnij Udostępnij Kontakt

Oba powyższe interfejsy mogą wydawać się bardzo podobne do siebie. Interfejs IQueryable implementuje interfejs IEnumerable:

namespace System.Linq
{
    //
    // Summary:
    //     Provides functionality to evaluate queries against a specific data source wherein
    //     the type of the data is not specified.
    public interface IQueryable : IEnumerable
    {
        Type ElementType { get; }

        Expression Expression { get; }

        IQueryProvider Provider { get; }
    }
}
Jednakże praktyczne wykorzystanie tych interfejsów jest różne. Spójrzmy na dwa poniższe przykłady napisane w ten sam sposób:
// Używamy EF aby połączyć się z naszą bazą bazą danych: Adventure Works
AdventureWorks2012_DataEntities db = new AdventureWorks2012_DataEntities();
// Tworzymy nowy obiekt pobierając wskazane dane
IEnumerable<Employee> employeeIEnumberable = db.Employee.Where(a =>; a.JobTitle.StartsWith("P"));
employeeIEnumberable = employeeIEnumberable.Take<Employee>(5);
// Tworzymy nowy obiekt pobierając wskazane dane
IQueryable<Employee> employeeIQueryable = db.Employee.Where(a => a.JobTitle.StartsWith("P"));
employeeIQueryable = employeeIQueryable.Take<Employee>(5);
Wykonanie pierwszego zapytania do bazy danych jest niewydajne. W pierwszej kolejności zostanie wykonane zapytanie zwracające wszystkie rekordy w których tytuł stanowiska pracy zaczyna się od literki "P". Kolejnym krokiem będzie pobranie 5 zwróconych rekordów. W przypadku naszej tabeli to nie jest problem. Wyobrażmy sobie, że mamy kilkaset tysięcy rekordów i wykonujemy takie zapytanie…

Zapytanie takie w języku SQL wygląda w poniższy sposób:
select * from HumanResources.Employee where JobTitle like 'P%';
Dopiero w następnym kroku zostaną zwrócone wymagane rekordy. W przypadku założonej przez nas liczby rzędu kilkuset tysięcy rekodów będzie to bardzo niewydajne zapytanie.

Z kolei w przypadku interfejsu IQueryable proces ten został zoptymalizowany. Zapytanie wygląda w następujący sposób:
select top(5) * from HumanResources.Employee where JobTitle like 'P%';
Z bazy danych zostaną odczytanie te wartości, których tak naprawdę potrzebujemy. Pokazuje to jak łatwo napisać kod, który w znaczący sposób wpłynie na spadek wydajności naszej aplikacji.