Jak odłączyć obiekty w Entity Framework Code First?

Odpowiedzi:

156

Jeśli chcesz odłączyć istniejący obiekt, postępuj zgodnie z radą @ Slauma. Jeśli chcesz wczytać obiekty bez śledzenia zmian użyj:

var data = context.MyEntities.AsNoTracking().Where(...).ToList();

Jak wspomniano w komentarzu, nie spowoduje to całkowitego odłączenia jednostek. Nadal są podłączone i leniwe ładowanie działa, ale jednostki nie są śledzone. Powinno to być używane na przykład, jeśli chcesz załadować encję tylko do odczytu danych i nie planujesz ich modyfikować.

Ladislav Mrnka
źródło
3
@Ladislav: Rzeczywiście, prawdopodobnie to miał na myśli programista Lol. Nigdy nie używałem i nie myślałem o tej metodzie, chociaż często ładuję listy obiektów i pozbywam się kontekstu na raz, coś w stylu using(ctx){ return ctx....ToList(); }. W takich przypadkach użycie AsNoTracking()miałoby sens, ponieważ zaoszczędziłbym niepotrzebnie wypełnianie kontekstu obiektu. Myślę, że prawdopodobnie przyniosłoby to korzyści w zakresie wydajności i zużycia pamięci, szczególnie w przypadku dużych list, prawda?
Slauma,
1
@Slauma: Tak, ma to wpływ na wydajność. Właśnie dlatego istnieje ta metoda. Użycie tego podejścia w ObjectContext API jest nieco bardziej skomplikowane.
Ladislav Mrnka
2
Czy to wyłącza leniwe ładowanie?
Shawn Mclean,
3
W rzeczywistości nie spowoduje to wyłączenia leniwego ładowania, a jedynie wyłączy śledzenie zmian i poprawi wydajność = jednostka jest nadal podłączona. Znalazłem go po udzieleniu odpowiedzi na to pytanie, więc jako prawidłową odpowiedź należy oznaczyć odpowiedź @ Slauma.
Ladislav Mrnka
1
To jest to czego chcę. Chcę leniwe ładowanie i możliwość modyfikowania tylko odłączonej jednostki.
Shawn Mclean,
255

To jest opcja:

dbContext.Entry(entity).State = EntityState.Detached;
Slauma
źródło
3
Czy mogę to zrobić podczas pobierania obiektów, które zwracają IQueryable?
Shawn Mclean
1
@Lol koder: Nie jestem pewien, czy dobrze cię rozumiem, ale entitymusi to być zmaterializowany obiekt typu, który jest częścią twoich klas modelowych (osoba, klient, zamówienie itp.). Nie można bezpośrednio przekazać IQueryable <T> do dbContext.Entry(...). Czy to było pytanie, które miałeś na myśli?
Slauma
9
@EladBenda: To zależy. Jeśli chcesz odłączyć obiekt, który jest już dołączony do kontekstu, ustaw stan na Detached. Jeśli chcesz załadować jednostki z bazy danych bez dołączania ich w ogóle do kontekstu (bez śledzenia zmian), użyj AsNoTracking.
Slauma,
1
Znalazłem ciekawy problem z tą metodą. Mimo że jednostka może być klasą proxy, ładowanie z opóźnieniem nie będzie działać po zmianie jego stanu na Detached.
kjbartel
4
@kjbartel: jest to oczekiwane zachowanie, ponieważ jednostka nie ma połączenia z kontekstem.
Ricardo Souza