Dzisiaj krótko o tym, jak poprawić wydajność pobierania danych z wykorzystaniem Entity Framework.
Entity Framework ma wbudowany mechanizm śledzenia zmian na obiektach. Dzięki niemu Entity Framework wie, który obiekt jest nowy i że trzeba go dodać do bazy, co można zaktualizować, jakie referencje usunąć, zmienić, itp. Ficzer niby fajny, ale często przeszkadza – szczególnie, jeżeli dane chcemy jedynie pobrać i wiemy, że nie będziemy ich modyfikować.
Problemem mechanizmu śledzenia jest narzut czasu i pamięci na wszystkie operacje. Dzieje się tak, ponieważ Entity Framework tworzy kopię obiektów pobieranych z bazy, a następnie porównuje je z obiektami, na których pracujemy. Samo porównanie wywoływane jest bardzo często, ale można je łatwo wyłączyć:
context.Configuration.AutoDetectChangesEnabled = false;
Problem w tym, że ten kod wyłącza jedynie automatyczne śledzenie, ale zmiany możemy zawsze wykryć ręcznie wywołując:
context.MyEntities.DetectChanges();
Oznacza to, że Entity Framework i tak tworzy kopie obiektów, przez co i tak tracimy na wydajności i wykorzystanej pamięci.
W sytuacjach, w których jedynie pobieramy dane z bazy (aby je później wyświetlić) należy w zapytaniu użyć metody AsNoTracking():
using (var context = new MyContext())
{
var entities = context.MyEntities.AsNoTracking().Where(e => e.IsActive);
}
Metoda ta całkowicie wyłączy mechanizm śledzenia, ale tylko w tym zapytaniu. Niestety nie ma możliwości ustawienia takiej reguły globalnie.
3 comments
Alternatywnie można także użyć właściwości MergeOption = NoTracking, np.
var entities = context.MyEntities.MergeOption = NoTracking;
Na czas życia kontekstu wyłączy śledzenie zmian.
Tak ale to rozwiązanie nie zadziała w przypadku klas POCO.
Comments are closed.