Die neue Untereinheit wird nicht gespeichert, wenn die übergeordnete Einheit gespeichert wird
-
02-01-2020 - |
Frage
Ich habe eine übergeordnete Entität
foo
was in der Datenbank vorhanden ist, ich habe eine Eigenschaft bar
auf dieser Entität (Eins-zu-viele-Beziehung).
Foo
ist getrennt, weil es mit WebApi deserialisiert wurde, also mache ich das foo
context.Foos.AddOrUpdate(foo);
Auch wenn es ein neues gibt bar
Wenn Sie einen daran angehängten Verweis hinzufügen, wird er nicht gespeichert, aber für eine andere Beziehung, die wir haben, funktioniert es auf diese Weise, nämlich eine Viele-zu-Viele-Beziehung.Wenn ich dieser Sammlung eine neue Entität hinzufüge, wird sie in ihrer Tabelle gespeichert und außerdem wird eine Zeile zur Beziehungstabelle hinzugefügt.
Wenn ich mache context.Bars.AddOrUpdate(foo.Bar);
bevor Sie anrufen context.Foos.AddOrUpdate(foo);
Der neue Balken wird korrekt in der Bar-Tabelle gespeichert, der Foo-Tabelle wird jedoch nicht die richtige Bar-ID hinzugefügt
@Yuliam Chandra
Wenn ich Ihre Antwort richtig verstehe (ich glaube, Sie verwechseln in Ihrer Antwort Bars und Foos), sollte das funktionieren?
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
Aber das ist nicht der Fall
Lösung
Für die Arbeit mit nicht verbundenen Objekten ist zusätzlicher Code erforderlich.
Wenn Sie mit nicht verbundenen Objekten arbeiten, müssen Sie die Synchronisation manuell verwalten.
Wenn Bar
Ist eine vorhandene Entität, müssen Sie sie zuerst anhängen Foo
wird hinzugefügt als Bar's
Kinder.
if (foo.Bar.Id != 0)
{
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
}
Das Beispiel des obigen Codes ist ähnlich mit Course
(Foo
) Und Department
(Bar
) Beispiel in Dieser Artikel.
Aber falls Bar
ist eine neue Entität, die Sie nur hinzufügen müssen Foo
, Dann Bar
wird auch hinzugefügt.
else
{
context.Foos.Add(foo);
}
Eine andere Sorte kann überprüft werden meine Antwort.
aktualisieren
Bevor ich es weiter erkläre, möchte ich identischen Code zeigen.
db.Set<T>().Add(instance)
ist gleichdb.Entry(instance).State = EntityState.Added;
db.Set<T>().Attach(instance)
ist gleichdb.Entry(instance).State = EntityState.Unchanged;
In der vorherigen Antwort wurden zwei Bedingungen erläutert.
Neues Foo und bestehende Bar
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
Neues Foo und neue Bar
context.Foos.Add(foo);
Speziell hinzugefügt
Added
hat eine besondere Bedingung, sobald eine Entität als markiert ist Added
.Alle Entitäten im Diagramm werden als markiert Added
auch wenn es sich bei einer Referenzentität um ein vorhandenes Objekt in der Datenbank handelt.Wenn wir diesen Code haben, werden Foo und Bar hinzugefügt.
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();
Um dies zu verhindern, muss zunächst die Stange angebracht werden.
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Bar>().Attach(bar);
db.Set<Foo>().Add(foo);
db.SaveChanges();
Überprüfen Artikel von Julie Lerman für eine ausführlichere Erklärung.
Der Grund dafür ist, dass bei Verwendung der DBSet.ADD ist auch markiert hinzugefügt.Auch wenn der Entwickler bekannt ist, dass das Thema einen vorhandenen ID -Wert hat, ehrt das Entity Framework seinen EntityState (hinzugefügt) und erstellt unabhängig von der vorhandenen ID einen Befehl zur Datenbankeinfügeeinsatz für das Thema.
Passen Sie die Erklärung basierend auf Ihrem Update an
Und Ihre aktualisierte Frage bezieht sich auf das bestehende Foo und die neue Bar.Wenn Sie Ihren Code verwenden, fügt das Ergebnis kein neues Bar hinzu und das vorhandene Foo stellt keine Beziehung zum neuen Bar her.
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
Wenn wir die Bar manuell zusammen mit hinzufügen AddOrUpdate(foo)
, das Ergebnis ist immer noch nicht wie erwartet.Die neue Bar wird hinzugefügt, aber Foo wird keine Beziehung zur neuen Bar haben.
db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);
Das Verhalten von AddOrUpdate
ist inkonsistent.
Lösung
Wenn Sie mit nicht verbundenen Objekten arbeiten, müssen Sie die Synchronisation manuell verwalten.
Dieser Code sollte unter allen Bedingungen funktionieren.
- Neues Foo und neue Bar
- Neues Foo und bestehende Bar
- Bestehende Foo und neue Bar
- Vorhandenes Foo und vorhandene Bar
Dieser Code hängt von der ID ab (id = 0 ist eine neue Entität).
db.Entry(foo).State =
foo.FooId == 0 ? EntityState.Added : EntityState.Modified;
if (foo.Bar != null)
{
db.Entry(foo.Bar).State =
foo.Bar.BarId == 0 ? EntityState.Added : EntityState.Modified;
^^^
// If you don't want to change the Bar while creating a relationship between
// Foo and with existing Bar, you can change
// `EntityState.Modified` with `EntityState.Unchanged`
}
db.SaveChanges();
Bezüglich AddOrUpdate
, Ich denke, es gibt ein offenes Problem, das gefunden werden kann Hier.