Entity Framework .Remove () vs. .DeleteObject ()

Antworten:

275

Es ist im Allgemeinen nicht richtig, dass Sie mit beiden Methoden " ein Element aus einer Datenbank entfernen " können. Um genau zu sein, ist es so:

  • ObjectContext.DeleteObject(entity)markiert die Entität wieDeleted im Kontext. (Es EntityStateist Deleteddanach.) Wenn Sie SaveChangesdanach aufrufen, sendet EF eine SQL- DELETEAnweisung an die Datenbank. Wenn keine referenziellen Einschränkungen in der Datenbank verletzt werden, wird die Entität gelöscht, andernfalls wird eine Ausnahme ausgelöst.

  • EntityCollection.Remove(childEntity)markiert die Beziehung zwischen Eltern und childEntityalsDeleted . Ob das childEntityselbst aus der Datenbank gelöscht wird und was genau beim Aufrufen passiert, SaveChangeshängt von der Art der Beziehung zwischen beiden ab:

    • Wenn die Beziehung optional ist , dh der Fremdschlüssel, der vom untergeordneten zum übergeordneten Element in der Datenbank verweist, NULLWerte zulässt , wird dieser Fremdschlüssel auf null gesetzt, und wenn Sie SaveChangesdiesen NULLWert für den aufrufen, childEntitywird er in die Datenbank geschrieben (dh die Beziehung zwischen die beiden werden entfernt). Dies geschieht mit einer SQL- UPDATEAnweisung. Es DELETEerfolgt keine Aussage.

    • Wenn die Beziehung erforderlich ist (die FK lässt keine NULLWerte zu) und die Beziehung nicht identifiziert wird (was bedeutet, dass der Fremdschlüssel nicht Teil des (zusammengesetzten) Primärschlüssels des Kindes ist), müssen Sie das Kind entweder einem anderen Elternteil hinzufügen oder Sie müssen das Kind explizit löschen (mit DeleteObjectdann). Wenn Sie dies nicht tun, wird eine referenzielle Einschränkung verletzt und EF löst beim Aufrufen eine Ausnahme aus SaveChanges- die berüchtigte Ausnahme " Die Beziehung konnte nicht geändert werden, da eine oder mehrere der Fremdschlüsseleigenschaften nicht nullwertfähig sind " oder ähnlich.

    • Wenn die Beziehung zu identifizieren (es notwendigerweise ist erforderlich dann , weil ein Teil des Primärschlüssels nicht sein kann NULL) wird EF die Markierung childEntityals Deletedauch. Wenn Sie SaveChangeseine SQL- DELETEAnweisung aufrufen , wird diese an die Datenbank gesendet. Wenn keine anderen referenziellen Einschränkungen in der Datenbank verletzt werden, wird die Entität gelöscht, andernfalls wird eine Ausnahme ausgelöst.

Ich bin tatsächlich etwas verwirrt über den Abschnitt "Bemerkungen" auf der von Ihnen verknüpften MSDN-Seite , da dort steht: " Wenn die Beziehung eine referenzielle Integritätsbeschränkung aufweist, markiert der Aufruf der Remove-Methode für ein abhängiges Objekt sowohl die Beziehung als auch das abhängige Objekt zum Löschen. ". Dies scheint mir ungenau oder sogar falsch zu sein, da alle drei oben genannten Fälle eine " referenzielle Integritätsbeschränkung " haben, aber nur im letzten Fall wird das Kind tatsächlich gelöscht. (Es sei denn, sie meinen mit " abhängigem Objekt " ein Objekt, das an einer identifizierenden Beziehung teilnimmt, was jedoch eine ungewöhnliche Terminologie wäre.)

Slauma
quelle
2
Referenzielle Integrität wikipedia: Die referenzielle Integrität ist eine Eigenschaft von Daten, bei deren Erfüllung jeder Wert eines Attributs (Spalte) einer Beziehung (Tabelle) als Wert eines anderen Attributs in einer anderen (oder derselben) Beziehung (Tabelle) vorhanden sein muss ), also wenn Beziehung optional ist, brechen wir die Datenintegritätsregel
Mohammadreza
3
@Mohammadreza: Wenn Sie NULLals "kein Wert" interpretieren (anstelle von "der Wert NULL", wie ich manchmal etwas schlampig schrieb), dann steht eine "optionale Beziehung" nicht im Widerspruch zu dieser Definition der referenziellen Integrität.
Slauma
1
Was ist die EF Core-Version von ObjectContext.DeleteObject?
Jonathan Allen
13

Wenn Sie "Gelöscht" wirklich verwenden möchten, müssen Sie Ihre Fremdschlüssel auf Null setzen, aber dann erhalten Sie verwaiste Datensätze (was einer der Hauptgründe ist, warum Sie dies überhaupt nicht tun sollten). Also einfach benutzenRemove()

ObjectContext.DeleteObject (Entität) markiert die Entität im Kontext als Gelöscht. (Danach wird EntityState gelöscht.) Wenn Sie anschließend SaveChanges aufrufen, sendet EF eine SQL DELETE-Anweisung an die Datenbank. Wenn keine referenziellen Einschränkungen in der Datenbank verletzt werden, wird die Entität gelöscht, andernfalls wird eine Ausnahme ausgelöst.

EntityCollection.Remove (childEntity) markiert die Beziehung zwischen parent und childEntity als gelöscht. Ob die childEntity selbst aus der Datenbank gelöscht wird und was genau passiert, wenn Sie SaveChanges aufrufen, hängt von der Art der Beziehung zwischen beiden ab:

Bemerkenswert ist, dass die Einstellung .State = EntityState.Deleted keine automatisch erkannte Änderung auslöst. ( Archiv )

Matas Vaitkevicius
quelle
4
Ok, für diejenigen, die meine Antwort ablehnen, hat das nichts mit Slaumas zu tun - beide verweisen auf dieselbe Dokumentation . Meins erklärt Beispiele aus dem wirklichen Leben, während seine Theorie Teil davon ist.
Matas Vaitkevicius