Die beiden Entitäten sind eine Eins-zu-Viele-Beziehung (erstellt durch Code First Fluent API).
public class Parent
{
public Parent()
{
this.Children = new List<Child>();
}
public int Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Data { get; set; }
}
In meinem WebApi-Controller habe ich Aktionen zum Erstellen einer übergeordneten Entität (die einwandfrei funktioniert) und zum Aktualisieren einer übergeordneten Entität (die ein Problem aufweist). Die Aktualisierungsaktion sieht folgendermaßen aus:
public void Update(UpdateParentModel model)
{
//what should be done here?
}
Derzeit habe ich zwei Ideen:
Rufen Sie eine nachverfolgte übergeordnete Entität ab, die
existing
von benannt istmodel.Id
, und weisen Siemodel
der Entität nacheinander Werte zu. Das klingt dumm. Und inmodel.Children
Ich weiß nicht, welches Kind neu ist, welches Kind geändert (oder sogar gelöscht) wird.Erstellen Sie eine neue übergeordnete Entität über
model
, hängen Sie sie an den DbContext an und speichern Sie sie. Aber wie kann der DbContext den Status von Kindern kennen (neu hinzufügen / löschen / geändert)?
Wie kann diese Funktion richtig implementiert werden?
quelle
Antworten:
Da das Modell, das auf dem WebApi-Controller veröffentlicht wird, von jedem Entity-Framework-Kontext (EF) getrennt ist, besteht die einzige Option darin, das Objektdiagramm (übergeordnetes Element einschließlich seiner untergeordneten Elemente) aus der Datenbank zu laden und zu vergleichen, welche untergeordneten Elemente hinzugefügt, gelöscht oder hinzugefügt wurden Aktualisiert. (Es sei denn, Sie würden die Änderungen mit Ihrem eigenen Verfolgungsmechanismus während des getrennten Zustands (im Browser oder wo auch immer) verfolgen, was meiner Meinung nach komplexer ist als der folgende.) Es könnte so aussehen:
...CurrentValues.SetValues
kann jedes Objekt übernehmen und Eigenschaftswerte basierend auf dem Eigenschaftsnamen der angehängten Entität zuordnen. Wenn sich die Eigenschaftsnamen in Ihrem Modell von den Namen in der Entität unterscheiden, können Sie diese Methode nicht verwenden und müssen die Werte einzeln zuweisen.quelle
existingParent.Children.Add(newChild)
untergeordneten Elementen können Sie dies nicht tun, da dann die Suche mit der vorhandenen Kinderlinie die kürzlich hinzugefügte Entität zurückgibt und diese Entität aktualisiert wird. Sie müssen nur in eine temporäre Liste einfügen und dann hinzufügen.existingChild
LINQ-Abfrage zu ändern :.Where(c => c.ID == childModel.ID && c.ID != default(int))
Ich habe mit so etwas rumgespielt ...
was Sie mit so etwas wie anrufen können:
Leider fällt dies irgendwie um, wenn es Sammlungseigenschaften für den untergeordneten Typ gibt, die ebenfalls aktualisiert werden müssen. Überlegen Sie, ob Sie versuchen möchten, dieses Problem zu lösen, indem Sie ein IRepository (mit grundlegenden CRUD-Methoden) übergeben, das für den eigenständigen Aufruf von UpdateChildCollection verantwortlich ist. Würde das Repo anstelle von direkten Aufrufen von DbContext.Entry aufrufen.
Ich habe keine Ahnung, wie sich das alles im Maßstab auswirkt, bin mir aber nicht sicher, was ich sonst mit diesem Problem anfangen soll.
quelle
toAdd.ForEach(i => (selector(dbItem) as ICollection<Tchild>).Add(i.Value));
sollte n -> n Problem lösen.Okay Leute. Ich hatte diese Antwort einmal, verlor sie aber auf dem Weg. absolute Folter, wenn Sie wissen, dass es einen besseren Weg gibt, sich aber nicht daran erinnern oder ihn finden können! Es ist sehr einfach. Ich habe es gerade auf verschiedene Arten getestet.
Sie können die gesamte Liste durch eine neue ersetzen! Der SQL-Code entfernt und fügt Entitäten nach Bedarf hinzu. Sie müssen sich damit nicht befassen. Achten Sie darauf, Kindersammlung oder keine Würfel einzuschließen. Viel Glück!
quelle
Wenn Sie EntityFrameworkCore verwenden, können Sie in Ihrer Controller-Post-Aktion Folgendes ausführen (Die Attach-Methode fügt rekursiv Navigationseigenschaften einschließlich Sammlungen hinzu):
Es wird davon ausgegangen, dass für jede aktualisierte Entität alle Eigenschaften festgelegt und in den Post-Daten des Clients angegeben sind (z. B. funktioniert dies nicht für die teilweise Aktualisierung einer Entität).
Sie müssen auch sicherstellen, dass Sie für diesen Vorgang einen neuen / dedizierten Entity Framework-Datenbankkontext verwenden.
quelle
So habe ich dieses Problem gelöst. Auf diese Weise weiß EF, welche zu aktualisieren sind.
quelle
Es gibt einige Projekte, die die Interaktion zwischen Client und Server vereinfachen, wenn es darum geht, ein gesamtes Objektdiagramm zu speichern.
Hier sind zwei, die Sie sich ansehen möchten:
Beide oben genannten Projekte erkennen die getrennten Entitäten, wenn sie an den Server zurückgegeben werden, erkennen und speichern die Änderungen und kehren zu den vom Client betroffenen Daten zurück.
quelle
Nur ein Proof of Concept
Controler.UpdateModel
funktioniert nicht richtig.Volle Klasse hier :
quelle
@ Charles McIntosh gab mir wirklich die Antwort auf meine Situation, indem das übergebene Modell abgetrennt wurde. Für mich hat es letztendlich funktioniert, zuerst das übergebene Modell zu speichern ... und dann die Kinder weiter hinzuzufügen, wie ich es bereits zuvor war:
quelle
Für VB.NET-Entwickler Verwenden Sie dieses generische Sub, um den untergeordneten Status zu markieren, der einfach zu verwenden ist
quelle
Quelle
quelle
Hier ist mein Code, der gut funktioniert.
quelle