2010-11-12 18 views
62

Zastanawiam się, dlaczego nie ma metody Detach na obiekcie DbContext, tak jak w ObjectContext. Mogę tylko założyć, że to zaniedbanie było zamierzone, ale trudno mi zrozumieć dlaczego. Muszę mieć możliwość odłączania i ponownego dołączania obiektów (na przykład do umieszczenia w pamięci podręcznej w projekcie ASP.NET). Ponieważ jednak nie mogę odłączyć obiektu, gdy próbuję dołączyć obiekt, który był powiązany z poprzednim kontekstem, otrzymuję wyjątek "Obiekt obiektu nie może być odwoływany przez wiele instancji wyjątku IEntityChangeTracker".Entity Framework Code First - No Detach() metoda na DbContext

Jakie są wytyczne? Czy czegoś brakuje?

+0

Czy ktoś cokolwiek do powiedzenia na temat: "Jakie są wytyczne tutaj? Czy brakuje mi czegoś?" Osobiście interesuje mnie tylko korzystanie z Detacha podczas szukania rozwiązania do odczytywania encji z kontekstu, tuż przed zapisaniem instancji pochodzącej z powrotem z interfejsu użytkownika. To daje mi "Obiekt z tym samym kluczem już istnieje w ObjectStateManager.ObjectStateManager nie może śledzić wielu obiektów z tym samym kluczem. " –

Odpowiedz

85

Dla osób które mogą natknąć się na to pytanie, ponieważ z CTP5, musisz teraz napisać:

((IObjectContextAdapter)context).ObjectContext 

aby dostać się do ObjectContext.

+1

+1 Muszę odwołać się do System.Data.Entity – Pandincus

+0

+1 Czysty, elegancki, jeden liniowiec, kocham go, a także chciałbym wrzucić, że interfejs znajduje się tutaj w szczególności: System.Data.Entity.Infrastructure.IObjectContextAdapter i tak jak Pandincus wskazał musisz zrobić odniesienie do System.Data.Entity też – dyslexicanaboko

38

DbContext wykorzystuje ObjectContext wewnętrznie i zespół EF uczynić ten dostępny jako chroniony własność tylko w przypadku, gdy kiedykolwiek potrzeba, aby spaść na niższy poziom API i brzmi jak to jest w tym przypadku, dzięki czemu można używać lub narazić wymagana funkcjonalność z DbContext pochodzącym:

public class YourContext : DbContext 
{ 
    public void Detach(object entity) 
    { 
     ObjectContext.Detach(entity);    
    } 
} 

Następnie można wywołać tę metodę z kontrolera do odłączenia podmiotu.

Alternatywnie, można zmienić go nawet bogatsze API:

public class YourContext : DbContext 
{ 
    public void ChangeObjectState(object entity, EntityState entityState) 
    { 
     ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState); 
    } 
} 

Oto jak DbContext wygląda z metadanych:

public class DbContext : IDisposable 
{  
    protected System.Data.Objects.ObjectContext ObjectContext { get; } 
    ... 
} 
+0

@Stacker to nie jest odpowiedź, ponieważ wymaga obsady przedstawionej w wybranej odpowiedzi powyżej, tzn.' DbContext' implementuje 'IObjectContextAdapter', nadając mu właściwość' ObjectContext' która jest inaczej dostępne, połączenie 2 odpowiedzi daje odpowiedź @ splite poniżej – eudaimos

+1

ChangeObjectState jest dość leniwy, używa "algorytmu liniowego z odlewem", który jest ... W pewnym sensie ... Wiesz ... Naprawdę źle. –

15

EF: CF 4.1 RC1 i EF: CF 4.1 RTW mają taką samą wyraźnie realizowany IObjectContextAdapter:

public static class DbContextExtensions 
{ 
    public static void Detach(this System.Data.Entity.DbContext context, object entity) 
    { 
     ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity); 
    } 
} 

Microsoft postanowił "Odłączyć jest zbyt zaawansowana technologia i powinny być ukryte". IMHO człowiek, który to wymyślił powinien zostać postrzelony - ponieważ jeśli dodasz całkiem nowy byt, trudno jest go po prostu usunąć bez zmiany zmian w db (możesz manipulować przy pomocy DbEntityEntry, ale to już inna historia).

Edycja 4 lata później:

Z EF6 (i jakoś pomijany EF5 :)) nie trzeba już detach(), poniewaz usuwania świeżo dodany wpis nie generuje delete from [table] where [Id] = 0 jak w EF4 - można po prostu zadzwonić i mySet.Remove(myFreshlyCreatedAndAddedEntity) wszystko będzie dobrze.

+0

shot? Kto i tak potrzebuje tej funkcji ?: P – quetzalcoatl

+1

@quetzalcoatl: 'var context = ...; var poco = new Poco(); context.Add (poco); context.Remove (poco); '<--- zgłasza wyjątek, ponieważ musisz go ZDEJMOWAĆ, nie usuwać - hej, odłączanie jest ukryte ... –

+1

(5 minut do edycji minęło, sry :)) W tym czasie byłem taki zły ... Kiedy tworzysz aplikację Windows, musisz mieć jakiś sposób, aby "anulować tworzenie nowego, prawdopodobnie niekompletnego wpisu, ale zachować kontekst UoW" ... Pozbywamy się całego EF btw i piszemy własną ORM: nie ma sposobu na wykorzystanie leniwego ładowania (mam kilka faktur i nie mogę załadować każdego InvoiceItem w pojedynczym zapytaniu "where InvoiceId in (xxyy)" - włącza nie działa w sposób, jakiego oczekiwaliśmy), większe repozytoria są leniwy leniwy (liniowy (!!!) wyszukiwanie przed każdym wykonaniem, wtf ...), tworzenie serwerów proxy dla ponad 100 typów poco zajmuje zbyt dużo czasu i tak dalej ... –

6

zwykle rozszerzenie klasy bazowej (dziedziczy z DbContext) z właściwością:

public class MyDbContext : DbContext 
{ 
    public ObjectContext ThisObjectContext 
    { 
     get 
     { 
      return ((IObjectContextAdapter)this).ObjectContext; 
     } 
    } 
} 

później można wykorzystać tę właściwość do różnych przydatnych rzeczy ... jak Detach :)

Powiązane problemy