Blog Dla Programistów C#/.NET

poniedziałek, 12 stycznia 2026

Entity Framework Core (EF Core) domyślnie śledzi (tracking) wszystkie pobrane encje. Oznacza to, że zmiany w tych obiektach zostaną wykryte i mogą być automatycznie zapisane w bazie danych podczas wywołania SaveChanges(). To wygodny mechanizm, gdy planujemy modyfikować dane, ale w pewnych sytuacjach może wprowadzać dodatkowy narzut na wydajność. Dlatego EF Core oferuje także tryb No-Tracking (np. poprzez metodę .AsNoTracking()), w którym pobrane encje nie są obserwowane pod kątem zmian. W tym artykule wyjaśnię, na czym polegają te 2 tryby i kiedy warto używać którego z nich, aby pisać wydajny i poprawny kod z EF Core.

EF Core: Tracking vs. No-Tracking - Kiedy Której Opcji Użyć?

Śledzenie encji w EF Core (Tracking)


Tryb śledzenia jest ustawieniem domyślnym dla zapytań w EF Core. Oznacza to, że kiedy wykonasz zapytanie zwracające encje, kontekst automatycznie doda te obiekty do swojego Change Tracker'a i będzie monitorował zmiany ich stanu. Jeśli zmienisz jakąś właściwość załadowanej encji, EF Core zaznaczy ją jako zmodyfikowaną, a wywołanie SaveChanges() wygeneruje odpowiednie polecenie SQL (np. UPDATE) i zaktualizuje bazę danych.

Dla zobrazowania, rozważmy prosty przykład kodu używającego tracking (śledzenia):

using var context = new MyDbContext();
/* Domyślnie: zapytanie śledzące */
var customer = context.Customers.First();
customer.Name = "Jan Kowalski"; /* modyfikacja właściwości encji */
context.SaveChanges(); /* EF Core wykrywa zmianę i zapisuje ją w bazie */

Po wykonaniu First() obiekt customer jest śledzony przez kontekst. Zmiana jego pola Name zostanie wykryta automatycznie, a SaveChanges() spowoduje aktualizację rekordu w bazie danych. Zaletą trybu śledzenia jest więc wygoda, EF Core sam zadba o oznaczenie encji jako zmodyfikowanej i ułatwi wykonanie operacji zapisujących.

Należy jednak pamiętać, że śledzenie niesie ze sobą koszt wydajnościowy. Kontekst przechowuje kopie oryginalnych wartości i informacje o każdej śledzonej encji. Przy dużej liczbie obiektów w pamięci może to zużywać więcej pamięci oraz czasu procesora na porównywanie zmian. Mimo to, tracking jest niezbędny w scenariuszach, gdy planujemy dokonać zmian w danych i zapisać je, wtedy jego zalety przeważają nad kosztem. Microsoft podkreśla, że nie powinno się wyłączać śledzenia, jeśli zamierzamy modyfikować encje i zapisywać te zmiany do bazy danych.


Zapytania bez śledzenia (No-Tracking)


W wielu sytuacjach aplikacja jedynie odczytuje dane z bazy, bez potrzeby ich modyfikacji. W takich przypadkach śledzenie zmian nie jest potrzebne, a nawet może niepotrzebnie obciążać aplikację. Zapytanie No-Tracking to takie, w którym wyłączamy mechanizm śledzenia, najczęściej poprzez dodanie metody .AsNoTracking() do zapytania LINQ. EF Core wtedy nie będzie przechowywał informacji o stanie tych encji, traktując je jako zwykłe obiekty POCO.

Główne korzyści podejścia No-Tracking to: mniejsze zużycie pamięci oraz szybsze wykonywanie zapytań (brak narzutu związanego z rejestrowaniem zmian obiektów). Zapytania no-tracking są zazwyczaj szybsze w scenariuszach tylko-do-odczytu właśnie dzięki pominięciu mechanizmu Change Tracker. W praktyce, przy dużej liczbie odczytywanych rekordów, użycie AsNoTracking() potrafi przyspieszyć operacje odczytu nawet o około 20% w porównaniu do domyślnego trybu.

Spójrzmy na przykład kodu z użyciem No-Tracking:

using var context = new MyDbContext();
/* Zapytanie bez śledzenia: */
var customer = context.Customers.AsNoTracking().First();
customer.Name = "Jan Nowak";
context.SaveChanges(); /* Nie zadziała: customer nie jest śledzony przez kontekst! */

Pobrany obiekt customer nie jest śledzony przez kontekst (dzięki AsNoTracking()). W efekcie powyższe wywołanie SaveChanges() nie zapisze zmiany nazwy w bazie, kontekst nie wie nic o modyfikacjach obiektu, którego nie śledzi. Jeśli w trybie No-Tracking jednak zechcemy zapisać zmiany takiego obiektu, musimy ręcznie poinformować o nich kontekst, np. wywołując context.Update(customer) lub ustawiając stan encji na Modified poprzez API kontekstu:

var customer = context.Customers.AsNoTracking().First();
customer.Name = "Jan Nowak";
/* Jawne oznaczenie encji jako zmodyfikowanej: */
context.Update(customer);
context.SaveChanges(); /* Teraz zmiana zostanie zapisana w bazie */

Naturalnie, powyższe rozwiązanie niweluje sens używania No-Tracking (skoro i tak musimy zarejestrować encję do śledzenia przed zapisem). Dlatego tryb bez śledzenia najlepiej sprawdza się przy operacjach czysto odczytowych, gdzie nie planujemy wcale wywoływać SaveChanges. Przykładowo, pobierając listę rekordów do wyświetlenia w raporcie lub na stronie WWW, możemy śmiało użyć AsNoTracking(), przyspieszy to zapytanie i zmniejszy zużycie pamięci, a nam i tak nie jest potrzebny mechanizm śledzenia zmian dla tych danych.

Uwaga: Możliwe jest także ustawienie globalnego trybu śledzenia dla kontekstu. Np. aby domyślnie wyłączyć śledzenie dla wszystkich zapytań można skonfigurować: optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) w ustawieniach kontekstu. Wówczas pojedyncze zapytania wymagające śledzenia można oznaczyć poprzez .AsTracking(). Jest to jednak zalecane tylko w specyficznych sytuacjach, na ogół wystarcza świadome używanie AsNoTracking tam, gdzie ma to sens.


Kiedy używać Tracking vs. No-Tracking?


Podsumujmy typowe scenariusze użycia obu podejść w EF Core:

Użyj standardowego śledzenia (Tracking), gdy:
    
• Planujesz modyfikować lub usuwać pobrane obiekty i zapisywać zmiany w bazie danych. W trybie śledzenia EF Core automatycznie wykryje zmiany i pozwoli je łatwo utrwalić.
    
• Chcesz korzystać z mechanizmów EF Core wymagających śledzenia, np. lazy loading, automatyczne ustawianie zależności/relacji czy Identity Resolution (zapewnienie, że ta sama encja nie pojawi się w kontekście wielokrotnie). Te funkcjonalności działają tylko dla śledzonych encji.
    
• Operujesz na stosunkowo niewielkiej liczbie encji w ramach jednego kontekstu, więc dodatkowy narzut pamięciowy i wydajnościowy nie będzie odczuwalny
      

Użyj zapytań No-Tracking, gdy:
    
• Pobierasz dane tylko do odczytu, np. wyświetlenia w interfejsie użytkownika, generacji raportu, eksportu itp., bez późniejszego zapisu tych obiektów. Nie ma sensu śledzić zmian czegoś, czego i tak nie zamierzasz zmieniać.
    
• Zależy Ci na maksymalnej wydajności odczytu i niskim zużyciu pamięci, np. ładujesz jednorazowo bardzo wiele rekordów. Wyłączenie śledzenia uprości pracę kontekstu i przyspieszy zapytanie.
    
• Masz długotrwały kontekst lub często wykonujesz podobne zapytania, brak śledzenia zapobiegnie "puchnięciu" kontekstu od tysięcy śledzonych obiektów, które już nie są potrzebne.

Krótko mówiąc, jeśli zamierzasz edytować dane - użyj tracking, a jeśli tylko czytasz - rozważ no-tracking dla lepszej wydajności. W razie wątpliwości możesz zawsze zacząć od domyślnego śledzenia (które zapewnia poprawność operacji), a optymalizację za pomocą AsNoTracking zastosować w miejscach, gdzie profilowanie wykaże taką potrzebę.


Podsumowanie


Zarówno tryb śledzenia, jak i tryb No-Tracking, mają swoje miejsce w EF Core. Tracking ułatwia operacje modyfikacji danych, automatycznie wykrywając zmiany i obsługując relacje między encjami, kosztem pewnego narzutu na wydajność. No-Tracking z kolei pozwala ten narzut zredukować w scenariuszach, gdzie chodzi wyłącznie o szybkie odczytanie danych, dzięki niemu zapytania wykonują się sprawniej, a pamięć nie zapełnia się niepotrzebnymi informacjami o stanie encji.

Wybór zależy więc od kontekstu: czy potrzebujesz zmieniać dane, czy tylko je odczytać. Świadome użycie AsNoTracking() w odpowiednich miejscach może przynieść wymierne korzyści wydajnościowe, natomiast domyślny mechanizm śledzenia zapewnia wygodę i bezpieczeństwo przy modyfikacjach danych.

Jeżeli chcesz lepiej poznać Entity Framework Core, zarówno podstawy, jak i zaawansowane techniki optymalizacji zapytań - zapraszam do mojego szkolenia online Szkoła Entity Framework Core. W szkoleniu pokazuję m.in. jak efektywnie korzystać z EF Core, tworzyć szybkie zapytania do bazy danych w C#/.NET oraz wiele więcej praktycznych zagadnień. Dzięki takiej wiedzy łatwiej zdecydujesz, kiedy sięgać po Tracking, a kiedy lepiej sprawdzi się No-Tracking, aby Twoje aplikacje działały wydajnie i poprawnie.

Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
CTO & Founder - FindSolution.pl
Programista C#/.NET. Specjalizuje się w Blazor, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz

Wyszukiwarka

© Copyright 2026 modestprogrammer.pl | Sztuczna Inteligencja | Regulamin | Polityka prywatności. Design by Kazimierz Szpin. Wszelkie prawa zastrzeżone.