2011-12-08 12 views
8

Mam projekt MVC i przy użyciu Entity Framework Code First i POCO obiektów dla bazy danych. Na przykład:Jak aktualizować podmioty powiązane w Entity Framework

public class ClassA 
{ 
    public int? Id {get; set;} 
    public string Name { get; set;} 
    public virtual ClassB B {get; set;} 
} 

public class ClassB 
{ 
    public int? Id {get;set;} 
    public string Description {get;set;} 
} 

Mam ActionResult, który tworzy lub edytuje model. Problem polega na wywołaniu tego ActionResult w celu zaktualizowania modelu, a zmieniono model.B, relacja nie jest zapisana w bazie danych. Kiedy wywoływany jest ActionResult w celu utworzenia nowego obiektu, działa on zgodnie z oczekiwaniami. Jak rozwiązać ten problem?

public ActionResult Save(ClassA model) 
{ 
    model.B = GetBFromDb(model.B.Id.Value); 

    if(ModelState.IsValid) 
    { 
    if (id.HasValue) 
    { 
     context.Entry(model).State = System.Data.EntityState.Modified; 
    } 
    else 
    { 
     context.ClassAs.Add(model); 
    } 
    context.SaveChanges(); 
    // redirect to index etc. 
    } 
    return View("EditForm", model); 
} 

Odpowiedz

3

Rozwiązałem to przez zmianę ClassA z klucza obcego do ClassB, i ustawienie wartości BId:

public class ClassA 
{ 
    public int? Id {get; set;} 
    public string Name { get; set;} 
    public int BId {get;set;} // foreign key to B 
    public virtual ClassB B {get; set;} 
} 

Dlaczego ta właściwość klucza obcego nie praca zamiast generowanego zagranicznej KY EF?

+3

w stanie rozłączonym, gdy nie masz klucza obcego, jest kilka luki, których EF nie może obejść i musisz udowodnić dodatkowy kod. W przeciwnym razie nie może zobaczyć związku. Dzięki właściwości FK jest to wartość skalarna i łatwiej EF może śledzić różne procesy. Naprawdę napisałem kolumnę z danymi z 2012 roku o tym dokładnym temacie! EF jest znacznie łatwiejszy w użyciu, gdy masz właściwość skalarną FK. W przeciwnym razie wiele funkcji, które chcesz "po prostu pracować", nie może i nie zmusza Cię do lepszego zrozumienia tego, co się dzieje i dostarczenia potrzebnych informacji. Niestety nie widziałem brakującego FK przed –

+0

@JulieLerman, bez problemu, dzięki za pomoc! :) – Marthijn

2

Nie można po prostu zadzwonić:

context.Entry(model).State = System.Data.EntityState.Modified; 

Jednostka musi być pobierane z kontekstu tak, że najpierw EF można rozpocząć śledzenie go. Następnie należy zastosować wszelkie zmiany w tym obiekcie przed wywołaniem context.SaveChanges().

var entity = context.ClassAs.Find(model.Id); 

// set properties you want to modify on entity 
entity.Name = model.Name; 
entity.ClassB = context.ClassBs.Find(model.ClassB.Id); 
// other changes to entity as required... 

context.SaveChanges(); 

W ten sposób EF śledzi entity i wie, aby zastosować wobec niego aktualizację.

+0

Dzięki temu działa! I jak ustawić "entity.ClassB = null;'? Wygląda na to, że ustawienie null nie działa. – Marthijn

+1

Yuck ... context.Entry (model) .State spowoduje, że kontekst będzie widział, czy model jest śledzony, a jeśli nie, zacznie go śledzić. Nie trzeba wykonywać innych zapytań db, aby śledzić instancję modelu. Problem związany z tym problemem polega na tym, że Entry ta metoda zmieni jedynie stan przekazanego obiektu. Ustawienie stanu "zmodyfikowanego" nie zostanie zastosowane do reszty wykresu. –

+0

@JulieLerman Dzięki znalazłem kilka samouczków, które również ustawić stan do modyfikacji. Ale nadal mam problem, że moje relacje się nie zaktualizują. – Marthijn

0

Po dołączeniu, a następnie ustawieniu stanu na zmodyfikowaną strukturę obiektu, zostaną wysłane wszystkie właściwości do aktualizacji. Nie musisz brać tutaj podejścia wydry, ponieważ powoduje to powstanie całego oddzielnego ładunku. Jeśli robisz to w ten sposób, nie ma sensu przechodzić w modelu, tylko identyfikator, a następnie wywołujesz TryUpdateModel, aby wypełnić właściwości z formularza.

Osobiście dołączyć jako zmodyfikowana tutaj jest nieco czystsze, gdyż nie wymaga kompletnego obie z powodu ładowania danych

http://geekswithblogs.net/michelotti/archive/2009/11/27/attaching-modified-entities-in-ef-4.aspx