2009-05-19 2 views
4

Wenn ich 2 Tabellen in meiner Datenbank habe: Foo und bar. Foo ist identifiziert durch FooId und Bar ist Identifier von BarId. A Bar kann 0 bis viele haben Foos deshalb hat Foo BarId als Fremdschlüssel.Kann System.Web.MVC.UpdateModel EF Navigation Properties aktualisieren?

Ich habe ein Modell, das diese und eine Ansicht darstellt, die verwendet werden können, eine Foo und wählen Sie zu bearbeiten (aus einem Drop-Down) die zugehörige Bar.

das folgende Verfahren auf dem Controller Gegeben:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Edit(int id, FormCollection formCollection) 
{ 
    Foo originalFoo = FooById(id); 

    if (!ModelState.IsValid) 
    { 
     return View(new VenueViewModel(originalVenue, _db.GetCounties(), _db.VenueTypeSet)); 
    } 

    UpdateModel(originalFoo); 

    /* Instead of using UpdateModel I could just iterate through 
     formCollection and manually update originalFoo, it would 
     work but surely there is a better way? */ 

    _db.SaveChanges(); 

    return RedirectToAction("Index"); 
} 

Der Aufruf Update wirft eine InvalidOperationException ohne Innerexception:

The model of type 'TestApplication.Models.Foo' was not successfully updated. 

Was für meinen Controller der richtige Weg ist um mein Entity Framework-basiertes Modell aus meiner Sicht aus dem Dropdown zu aktualisieren?

Antwort

7

Nein, der Standardmodellbinder kann dies nicht. Sie würden es schwer haben, auch ein benutzerdefiniertes Modellbinder zu schreiben. Das HTML-SELECT-Element speichert nur einen ID-Wert in der Beschreibung, der nicht ausreicht, um die meisten Entitätsinstanzen zu materialisieren. Wir haben also nur damit zu tun, dass wir nur eine ID bekommen, was nicht ausreicht, um eine Entität zu materialisieren, ohne die Datenbank zu treffen.

Wenn daher ein Unternehmen Navigationseigenschaft zu aktualisieren, haben wir zwei Möglichkeiten:

  1. lesen in der Entität aus der Datenbank und weisen Sie auf die Navigationseigenschaft in der Steuerung.
  2. Versuchen Sie nicht, eine Entität für die Navigationseigenschaft zu materialisieren; instead just assign the EntityKey.

Letzteres ist was ich tue. Sie können dies in einem benutzerdefinierten Modellbinder oder in einem Controller tun. Sie können viel, viel mehr darüber lesen, indem Sie den Link verwenden, und ich habe einen Beispielcode in den Kommentaren zu diesem Link.

Die neue Version des Entity Framework in der kommenden .NET 4.0 wird eine neue Funktion namens "FK Associations" haben, die das erheblich vereinfachen wird.

+0

Die neue Version von .NET (4.0) mit EFv4 führt zwar Fremdschlüssel in Entitäten ein, aber wenn wir EditorFor() in unseren Ansichten und eine benutzerdefinierte Vorlage für unseren Typ verwenden, der stark in den Typ der Navigationseigenschaft eingegeben wird Der Standardmodellbinder bindet dann erfolgreich die Eigenschaften der Navigationseigenschaft an die POSTed-Werte aus der Vorlage "EditorFor". Dies ist jedoch immer noch nicht genug für die SaveChanges() für den Kontext zu arbeiten. Es Fehler mit entweder 1) Primärschlüssel existiert bereits oder 2) kann nicht ändern den Primärschlüssel der verbundenen Einheit (wir ändern es nicht tatsächlich) aber immer noch .. – mare

+0

und die Standard-Ordner überspringt die Fremdschlüssel-Eigenschaft, daher sind wir links mit einer Option, um diese Eigenschaft manuell festzulegen und die Navigationseigenschaft auf null zu belassen. Dann funktioniert es und speichert die Änderungen. – mare

+0

Ist es nicht möglich, den Modellbinder in Verbindung mit dem Anbringen des Objekts zu verwenden? Z.B. Wenn die Dropdown-Liste den Namen "Bar.Id" hat und der Modellordner ein Foo-Element ("myNewFoo" nennen) aus dem Formular erstellt, wird "myNewFoo.Bar.Id" ausgefüllt. Könnten Sie dann nicht 'db.BarTable.Attach (myNewFoo.Bar);'? – Flater

Verwandte Themen