Cache oraz Future z EF Plus

Wprowadzenie

Tak jak zapowiedziałem w poprzednim wpisie, w tym również będę kontynuował opisywanie biblioteki Entity Framework Plus, która rozszerza Entity Framework o przydatne funkcjonalności. Tym razem skupimy się na dwóch. Pierwszą będzie cache drugiego poziomu, natomiast drugą grupowanie wykonywania zapytań w jednej operacji na bazie z wykorzystaniem funkcji Future.

W przykładzie będziemy bazowali na demie z poprzedniego wpisu o filtrowaniu w Entity Framework Plus. Dlatego zachęcam Cię do jego przeczytania, jeśli tego jeszcze nie zrobiłeś(-łaś).

Cache w Entity Framework Plus

Domyślnie Entity Framework ma wbudowany tylko cache pierwszego poziomu, czyli zapisuje i wykorzystuje ponownie obiekty modelu wykorzystywane przez DataContext (DbContext). W przypadku cache’owania drugiego poziomu (który umożliwia zapisanie i ponowne wykorzystanie danych z całego zapytania) musimy posiłkować się dodatkową biblioteką. Entity Framework Plus jest właśnie takim dodatkowym narzędziem, które dostarcza nam cache drugiego poziomu.

W przykładzie zaczniemy od dwukrotnego pobrania listy aktywnych kategorii, aby zobaczyć, że na początku zapytanie wykonuje się dwa razy:

public class CacheDemo
{
public void Run()
{
WithoutCache();
}
private void WithoutCache()
{
using (var db = new DataContext())
{
var categories = db.Categories.Where(c => c.IsActive).ToList();
Console.WriteLine($"Categories count: {categories.Count}");
categories = db.Categories.Where(c => c.IsActive).ToList();
Console.WriteLine($"Categories count: {categories.Count}");
}
}
}

W wyniku działania powyższego kodu na bazie wykonało się dwa razy zapytanie:

SELECT [Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[IsActive] AS [IsActive]
FROM [dbo].[Categories] AS [Extent1]
WHERE [Extent1].[IsActive] = 1

Widać to w profilerze (przy okazji polecam wpis o profilowaniu zapytań w Entity Framework Profiler):

ef plus cache two query

Aby skorzystać z drugiego poziomu cache z Entity Framework Plus, należy przed wywołaniem metody ToList (lub innej metody, która materializuje dane) wywołać metodę FromCache. Wtedy Entity Framework w pierwszej kolejności sprawdzi, czy ma zapisany wynik zapytania; jeśli tak, to go zwróci, a jeśli nie, to wykona zapytanie i zapisze jego wynik w cache.

Zmodyfikowany kod wygląda tak:

public class CacheDemo
{
public void Run()
{
WithCache();
}
private void WithCache()
{
using (var db = new DataContext())
{
var categories = db.Categories.Where(c => c.IsActive).FromCache().ToList();
Console.WriteLine($"Categories count: {categories.Count}");
categories = db.Categories.Where(c => c.IsActive).FromCache().ToList();
Console.WriteLine($"Categories count: {categories.Count}");
}
}
}
view raw WithCache.cs hosted with ❤ by GitHub

W efekcie na bazie wykona się jedno zapytanie:

ef plus cache one query

Ten mechanizm cache’owania możemy również konfigurować. Możemy na przykład przypisać tag dla takiego zapytania i później, w momencie gdy wiemy, że dane w bazie się zmieniły, możemy usunąć cache dla przypisanego taga. Podobnie jak to opisałem podczas pokazywania Cache Managera.

Możemy również określać, jak długo dane mają być zapisane w cache. Po więcej szczegółów zapraszam do dokumentacji – https://entityframework-plus.net/query-cache.

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 30 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?

Future w Entity Framework Plus

Drugim ciekawym i czasami przydatnym mechanizmem, który opiszę w tym wpisie, jest wykorzystanie metody Future (https://entityframework-plus.net/query-future).

Entity Framework, w momencie gdy korzystamy z takich metod jak FirstOrDefault, ToList itd., od razu wykonuje takie zapytanie na bazie danych. W niektórych sytuacjach takie podejście może być nie do końca optymalne. Na przykład w sytuacji, gdy tworzymy jakiś bardziej rozbudowany obiekt, często wcześniej pobieramy powiązane obiekty za pomocą ich identyfikatorów – takie pobranie jest wykonywane w oddzielnej operacji na bazie. Gdy mamy pięć takich powiązanych obiektów, wykonujemy wtedy pięć operacji na bazie.

Metoda Future z Entity Framework Plus umożliwia nam grupowanie takich operacji poprzez odłożenie ich na przyszłość i wykonanie ich później w jednej operacji na bazie danych.

Najlepiej zobaczyć to na przykładzie. Poniżej znajduje się kod, który pobiera jedną kategorię oraz produkt na podstawie id w sposób standardowy:

public class FutureDemo
{
public void Run()
{
WithoutFuture();
}
private void WithoutFuture()
{
using (var db = new DataContext())
{
var categoryQuery = db.Categories.Where(c => c.Id == 1);
var productQuery = db.Products.Where(c => c.Id == 1);
var category = categoryQuery.FirstOrDefault();
var product = productQuery.FirstOrDefault();
Console.WriteLine($"Category: {category.Name}, Product: {product.Name}");
}
}
}

W wyniku działania powyższego kodu na bazie wykonają się dwa zapytania w dwóch operacjach:

ef plus future two trip to database

Wykorzystanie metody Future jest dość proste: dodajemy jej wywołanie do zapytań, które mają zostać wykonane w jednej operacji na bazie. Później, podczas wykonywania pierwszego, automatycznie wykonają się wszystkie inne. W kodzie wygląda to tak:

public class FutureDemo
{
public void Run()
{
WithFuture();
}
private void WithFuture()
{
using (var db = new DataContext())
{
var categoryQuery = db.Categories.Where(c => c.Id == 1).Future();
var productQuery = db.Products.Where(c => c.Id == 1).Future();
var category = categoryQuery.FirstOrDefault();
var product = productQuery.FirstOrDefault();
Console.WriteLine($"Category: {category.Name}, Product: {product.Name}");
}
}
}
view raw WithFuture.cs hosted with ❤ by GitHub

Natomiast w profilerze wygląda to tak:

ef plus future one trip to database

Czyli w jednej operacji na bazie wykonywane są dwa zapytania. W przypadku grupowania większej liczby zapytań może to pozytywnie wpłynąć na obciążenie oraz efektywność systemu.

Przykład

Na githubie (https://github.com/danielplawgo/EFPlus) rozbudowałem przykład z wpisu o filtrowaniu w Entity Framework Plus. Dodałem w nim dodatkowe klasy z testami dla cache oraz Future. Po pobraniu przykładu należy ustawić w app.config poprawny connection string do bazy testowej.

Podsumowanie

Mam nadzieję, że po raz kolejny udało mi się pokazać Ci, że gdy używasz Entity Framework w swoich projektach, to warto również znać darmowe rozszerzenie Entity Framework Plus. Biblioteka ta powoduje, że praca z Entity Framework jest dużo bardziej przyjemna i efektywna. Wręcz nie wypada jej nie znać tej.

W jednym z przyszłych wpisów poruszę jeszcze temat płatnej biblioteki od ZZZ Projects – Entity Framework Extensions – https://entityframework-extensions.net.

Szkolenie Entity Framework Core

Szkolenie Entity Framework Core

Zainteresował Ciebie ten temat? A może chcesz więcej? Jak tak to zapraszam na moje autorskie szkolenie z Entity Framework Core.

1 thought on “Cache oraz Future z EF Plus

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.