Filtrowanie w Entity Framework Plus

Wprowadzenie

Entity Framework jest dość przyjemnym narzędziem do pracy z danymi w aplikacji. Prawie każdy, kto spróbował w nim pracy, nie ma za dużej ochoty wracać do pisania zapytań w czystym SQLu. Ale niestety ma też swoje problemy, o których już nieraz pisałem. Na szczęście mamy takie firmy jak np. ZZZ Project, które tworzą biblioteki rozwiązujące te problemy.

W tym wpisie chciałbym przedstawić Ci kolejną funkcjonalność darmowej biblioteki Entity Framework Plus. Wcześniej pokazałem, w jaki sposób efektywniej aktualizować dane bez ich pobierania oraz jak zapisywać historię zmian danych. Natomiast teraz zobaczymy, jak efektywnie filtrować dane.

Przykład do testów

Zanim przejdę do omawiania kolejnych funkcji, zrobię małe wprowadzenie do projektu, na którym będziemy je testowali.

Jest to mniej więcej ten sam przykład, którego używam w większości wpisów. W testowej aplikacji mamy trzy klasy modelu: BaseModel, Category oraz Product, przy czym kategoria oraz produkt są połączone relacją jeden do wielu:

Do tego DataContext:

W przykładzie dodałem również generowanie danych testowych z wykorzystaniem biblioteki Bogus w metodzie Seed, która dodaje 10 kategorii oraz 100 produktów.

Filtrowanie w Entity Framework Plus

Pierwszą funkcjonalnością, którą opiszę, jest filtrowanie. Dzięki niemu możemy łatwiej i efektywniej zarządzać dodatkowymi warunkami, która muszą zostać uwzględnione w zapytaniach. W moich aplikacjach każda klasa modelu ma właściwość IsActive, która określa, czy dane są dostępne, czy może oznaczone jako usunięte. Następnie w zapytaniach dodajemy warunek, w którym sprawdzamy, czy IsActive jest ustawione na true.

Niestety takie podejście powoduje, że wcześniej czy później w jakimś miejscu zapomnimy dodać ten warunek i wtedy aplikacja zwróci błędne dane. Właśnie w tym miejscu przydaje się filtrowanie z Entity Framework Plus.

Filtry możemy skonfigurować zaraz po utworzeniu instancji DataContext. Określamy, dla jakiego typu definiujemy filtr oraz jaki on jest. Później tego warunku nie musimy powtarzać w samym zapytaniu:

Powyższa metoda dodaje filtr dla klasy Product, który ustawia warunek, aby IsActive miało wartość true. Pobieramy i wyświetlamy liczbę produktów (tych aktywnych). W dalszej części metody pobieramy kategorie z bazy i wyświetlamy liczbę produktów w tej kategorii (korzystamy z właściwości Products oraz lazy loading).

W wyniku działania powyższego kodu na bazie na tabeli Products zostaną wykonane zapytania:

Widać, że w obu zapytaniach jest dodany warunek dla IsActive, mimo że w samym zapytaniu tego nie ma.

Taki sposób filtrowanie jest bardzo fajny. Szczególnie w przypadku korzystania z dodatkowych właściwości do pobierania danych zamiast korzystania bezpośrednio z DataContext, jak to jest w przypadku drugiego zapytania. O ile w przypadku pierwszego pobrania liczby produktów możemy sobie to opakować w wywołanie repozytorium, tam dodać warunek i zapomnieć o nim, o tyle w drugim przypadku już musimy pamiętać o dodatkowym warunku.

Darmowy kurs Visual Studio

Pracując z setkami programistów, zauważyłem, że większość osób nie pracuje efektywnie w Visual Studio. W skrajnych przypadkach korzystali z kopiowania z wykorzystaniem menu Edit. Wiem, że to dziwne, ale naprawdę niektórzy tak pracują. Dlatego postanowiłem stworzyć kurs Visual Studio – aby pomóc koleżankom i kolegom w efektywniejszej pracy.

Przygotowałem 20 lekcji e-mail, w których pokażę Ci, w jaki sposób pracować efektywniej i szybciej w Visual Studio. Poznasz dodatki, bez których nie wyobrażam sobie pracy w tym IDE.

Po więcej informacji zapraszam na dedykowaną stronę kursu: Darmowy Kurs Visual Studio.

Quiz C#

Ostatnio przygotowałem również quiz C#, w którym możesz sprawdzić swoją wiedzę. Podejmiesz wyzwanie?

Globalne filtry

Powyższy kod dodawał filtrowanie na poziomie instancji pojedynczego obiektu DataContext. Możemy również zrobić to globalnie dla wszystkich instancji. Robi się to bardzo podobnie, różnica polega na tym, czym wywołujemy metodę Filter:

Efekt działania jest taki sam, dlatego nie będę wrzucał jeszcze raz tego samego SQLa.

Dzięki filtrom globalnym możemy w jednym miejscu zdefiniować filtry dla całej aplikacji bez konieczności określania tego w poszczególnych instancjach.

Filter IsActive jest przykładem takiego warunku, który warto zdefiniować sobie globalnie.

Niektóre filtry są natomiast filtrami typowo lokalnymi – w przypadku tworzenia aplikacji typu multitenant, w której mamy jedną bazę dla wszystkich klientów/aplikacji i w której każdy rekord ma przypisany identyfikator aplikacji. W takiej sytuacji możemy wykorzystać lokalny filtr, który ustawi warunek dla id aplikacji na podstawie zalogowanego użytkownika, gdzie poszczególne warunki między użytkownikami różnią się wartością tego identyfikatora. W takiej sytuacji globalny filtr za bardzo nie zadziała.

Wyłączenie filtrowania

W przypadku gdy korzystamy z filtrów globalnych (ale w lokalnych też to działa), możemy wyłączyć filtrowanie. W przypadku warunku IsActive czasami mamy potrzebę wyłączenia go. Gdy wyświetlamy historyczne zamówienie dla produktu, który został „usunięty”, musimy wyłączyć warunek, aby móc takie dane historyczne pokazać.

Filtr wyłącza się na poziomie zapytania z wykorzystaniem metody AsNoFilter:

W efekcie otrzymamy zapytanie bez warunku dla IsActive:

Entity Framework Plus umożliwia też bardziej rozbudowane konfigurowanie włączania oraz wyłączania filtrowania. Opcji jest sporo, ale osobiście z nich nie korzystałem, ponieważ nie wiem, czy czasem na dłuższą metę takie podejście za bardzo nie komplikuje utrzymania aplikacji. Polecam przejrzenie dokumentacji, może znajdziesz coś ciekawego dla siebie w tym temacie – https://entityframework-plus.net/query-filter.

Filtrowanie i early loading

Filtrowanie z Entity Framework Plus działa również w przypadku korzystania z metody Include:

Pierwsza metoda wykorzystuje Include bez filtra, druga występuje z filtrem dla IsActive. Wykonanie powyższego kodu daje takie zapytania na bazie:

Oba zapytania są bardzo podobne, ale w linijce 49 listingu widać, że pojawia się dodatkowy warunek dla IsActive, którego nie było wcześniej, co jest tutaj bardzo fajne i przydatne. Nie musimy później pisać dodatkowego kodu po stronie aplikacji, który dodatkowo pobiera mniejszą liczbę danych.

Przykład

Na githubie (https://github.com/danielplawgo/EFPlus) znajduje się już klasycznie przykład dla tego wpisu. Po jego pobraniu należy ustawić poprawny connection string w app.confing.

Podsumowanie

Entity Framework Plus jest biblioteką, której nie wypada nie znać (a tym bardziej nie wypada z niej niekorzystać) w momencie, gdy korzystamy z Entity Framework w aplikacji. Mechanizm filtrowania, który pokazałem Ci w tym wpisie, jest bardzo fajny i wygodny. Za jego pomocą możemy znacząco ułatwić sobie pisanie kodu (w szczególności podczas korzystania z lazy/early loading). A dodatkowo zabezpieczymy się przed brakującymi warunkami w aplikacji (np. dla IsActive).

Za tydzień pozostaniemy w temacie Entity Framework Plus. Pokażę Ci pozostałe funkcjonalności, które również warto znać.

1 thought on “Filtrowanie w Entity Framework Plus

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *