Jaką różnicę robi .AsNoTracking ()?

228

Mam pytanie dotyczące .AsNoTracking()rozszerzenia, ponieważ jest to całkiem nowe i dość mylące.

Używam kontekstu na żądanie dla witryny.

Wiele moich bytów się nie zmienia, więc nie trzeba ich śledzić, ale mam następujący scenariusz, w którym nie jestem pewien, co się dzieje z bazą danych, a nawet czy to ma znaczenie w tym przypadku.

Ten przykład to, co obecnie robię:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

Jest to to samo co powyżej, ale usuwa .AsNoTracking()z kroku 1:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

Kroki 1 i 2 wykorzystują ten sam kontekst, ale występują w różnych momentach. Nie mogę wypracować, czy jest jakaś różnica. Ponieważ krok 2 jest aktualizacją, obaj i tak trafią do bazy danych dwa razy.

Czy ktoś może mi powiedzieć na czym polega różnica?

dotnetnoob
źródło

Odpowiedzi:

187

Różnica polega na tym, że w pierwszym przypadku odzyskany użytkownik nie jest śledzony przez kontekst, więc jeśli zamierzasz zapisać użytkownika z powrotem do bazy danych, musisz go dołączyć i ustawić poprawny stan użytkownika, aby EF wiedział, że powinien zaktualizować istniejącego użytkownika zamiast wstawiania nowego. W drugim przypadku nie musisz tego robić, jeśli ładujesz i zapisujesz użytkownika z tą samą instancją kontekstu, ponieważ mechanizm śledzenia obsługuje to za Ciebie.

Ladislav Mrnka
źródło
1
Czy możemy uzyskać takie same korzyści dla anonimowych klas w wybranych zapytaniach, takich jak kontekst.Users.Select (u => new {Name = u.Name})? Dzięki.
Dilhan Jayathilake,
6
@DilhanJayathilake: Anonimowe klasy nie reprezentują samej istoty, więc nie mają śledzenia.
Ladislav Mrnka
1
Ponieważ EF6 czasami wprowadza niepoprawnie klucz encji w widoku, funkcja AsNoTracking () ignoruje klucz i dlatego jest alternatywą dla ręcznego naprawiania klucza (zakładając, że inne zalety klucza nie są potrzebne).
crokusek
4
Należy również pamiętać, że największy efekt AsNoTracking polega na tym, że leniwe ładowanie nie działa
Douglas Gaskell
170

zobacz tę stronę Entity Framework i AsNoTracking

Co robi AsNoTracking

Entity Framework udostępnia wiele opcji dostrajania wydajności, które pomagają zoptymalizować wydajność aplikacji. Jedną z tych opcji strojenia jest .AsNoTracking(). Ta optymalizacja pozwala powiedzieć, aby Entity Frameworknie śledzić wyników zapytania. Oznacza to, że Entity Frameworknie wykonuje żadnego dodatkowego przetwarzania ani przechowywania jednostek zwracanych przez zapytanie. Oznacza to jednak również, że nie można zaktualizować tych elementów bez ponownego dołączenia ich do wykresu śledzenia.

przy użyciu AsNoTracking można uzyskać znaczny wzrost wydajności

Moji
źródło
11
Wygląda na to, że zyski mogą być czasem równoważone: stackoverflow.com/questions/9259480/...
Fabrice
3
Mój wzrost wydajności dzięki złożonemu zapytaniu ładującemu relację nadrzędną z dzieckiem w jednym kroku wyniósł około 50%
Karl
53

Brak śledzenia zapytań LINQ do encji

Użycie AsNoTracking () jest zalecane, gdy twoje zapytanie jest przeznaczone do operacji odczytu. W tych scenariuszach odzyskujesz swoje byty, ale nie są one śledzone przez kontekst, co zapewnia minimalne zużycie pamięci i optymalną wydajność

Plusy

  1. Poprawiona wydajność w porównaniu ze zwykłymi zapytaniami LINQ.
  2. W pełni zmaterializowane przedmioty.
  3. Najprostszy do pisania ze składnią wbudowaną w język programowania.

Cons

  1. Nie nadaje się do operacji CUD.
  2. Niektóre ograniczenia techniczne, takie jak: Wzorce używające DefaultIfEmpty dla zapytań OUTER JOIN powodują, że zapytania są bardziej złożone niż proste instrukcje OUTER JOIN w encji SQL.
  3. Nadal nie możesz używać LIKE z ogólnym dopasowaniem wzorów.

Więcej informacji dostępnych tutaj:

Uwagi dotyczące wydajności dla Entity Framework

Entity Framework i NoTracking

NullReference
źródło
10

AsNoTracking () pozwala na ominięcie wymogu „unikalnego klucza na rekord” w EF (niewymienionego wyraźnie innymi odpowiedziami).

Jest to niezwykle pomocne podczas czytania Widoku, który nie obsługuje unikatowego klucza, ponieważ być może niektóre pola są zerowalne lub natura widoku nie jest logicznie indeksowana.

W tych przypadkach „klucz” może być ustawiony na dowolną kolumnę, która nie ma wartości zerowej, ale następnie AsNoTracking () musi być używany z każdym zapytaniem, w przeciwnym razie rekordy (duplikaty według klucza) zostaną pominięte.

Crokusek
źródło
2
Aby przypomnieć o tym, jak ważne jest to w Widoku, mam zapytanie z widoku, które zwraca 7 unikalnych rekordów po uruchomieniu przez SSMS. Kiedy uruchamiam przez EF, bez modyfikatora AsNoTracking, otrzymuję pierwszy rekord, trzy kopie drugiego i trzy kopie trzeciego. Naprawdę wymagało to wiele niewiarygodnego drapania w głowę, a to naprawiało za pomocą AsNoTracking!
Ade
Miałem dokładnie ten sam problem podczas korzystania z Linq do encji podczas odpytywania widoku bez kluczy podstawowych. Dowiedziałem się o AsNoTracking dopiero po pół dnia drapania głowy. Ten post na forum ASP.Net doprowadził mnie do tego. forums.asp.net/t/…
red_dorian
6

Jeśli masz coś innego, co zmienia DB (powiedzmy inny proces) i musisz upewnić się, że widzisz te zmiany, użyj AsNoTracking(), w przeciwnym razie EF może dać ci ostatnią kopię, którą miał kontekst, dlatego dobrze jest zwykle używać nowego kontekstu przy każdym zapytaniu :

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

Andrzej Pasztet
źródło