webentwicklung-frage-antwort-db.com.de

Entity Framework 4 - AddObject vs Attach

Ich habe kürzlich mit Entity Framework 4 gearbeitet und bin etwas verwirrt, wann ObjectSet.Attach und ObjectSet.AddObject zu verwenden sind.

Meinem Verständnis nach:

  • Verwenden Sie "Anhängen", wenn bereits eine Entität im System vorhanden ist
  • Verwenden Sie "AddObject", wenn Sie eine brandneue Entität erstellen

Also, wenn ich eine neue Person erstelle , mache ich das.

var ctx = new MyEntities();
var newPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.AddObject(newPerson);
ctx.SaveChanges();

Wenn ich eine bestehende Person ändere , mache ich das:

var ctx = new MyEntities();
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
existingPerson.Name = "Joe Briggs";
ctx.SaveChanges();

Denken Sie daran, dies ist ein sehr einfaches Beispiel. In der Realität verwende ich Pure POCOs (keine Codegenerierung), Repository-Muster (nicht mit ctx.Persons umgehen) und Unit of Work (nicht mit ctx.SaveChanges umgehen). Aber "under the covers" ist das, was in meiner Implementierung passiert.

Nun, meine Frage - Ich bin noch nicht in der Lage, ein Szenario zu finden, in dem ich Anhängen .

Was vermisse ich hier? Wann müssen wir Attach verwenden?

[~ # ~] edit [~ # ~]

Zur Verdeutlichung suche ich Beispiele wann ich Attach over AddObject verwenden soll (oder umgekehrt).

EDIT 2

Die folgende Antwort ist richtig (was ich akzeptiert habe), aber ich dachte, ich würde ein weiteres Beispiel hinzufügen, in dem Attach nützlich wäre.

In meinem obigen Beispiel zum Ändern einer vorhandenen Person werden tatsächlich zwei Abfragen ausgeführt.

Eine zum Abrufen der Person (.SingleOrDefault) und eine zum Ausführen des UPDATE (.SaveChanges).

Wenn ich (aus irgendeinem Grund) bereits wusste, dass "Joe Bloggs" im System vorhanden ist, warum sollte ich eine zusätzliche Abfrage durchführen, um ihn zuerst zu erhalten? Ich könnte das machen:

var ctx = new MyEntities();
var existingPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.Attach(existingPerson);
ctx.SaveChanges();

Dies führt dazu, dass nur eine UPDATE-Anweisung ausgeführt wird.

127
RPM1984

ObjectContext.AddObject und ObjectSet.AddObject:
Die Methode AddObject dient zum Hinzufügen neu erstellter Objekte, die not sind in der Datenbank vorhanden. Die Entität erhält ein automatisch generiertes temporäres EntityKey und ihr EntityState wird auf Added gesetzt. Wenn SaveChanges aufgerufen wird, wird dem EF klar, dass diese Entität in die Datenbank eingefügt werden muss.

ObjectContext.Attach und ObjectSet.Attach :
Andererseits wird Attach für Entitäten verwendet, die bereits existieren exist in der Datenbank. Anstatt den EntityState auf Hinzugefügt zu setzen, führt das Anhängen zu einem Unverändert EntityState, was bedeutet, dass er sich seit dem Anhängen an den Kontext nicht geändert hat. Es wird davon ausgegangen, dass Objekte, die Sie anhängen, in der Datenbank vorhanden sind. Wenn Sie die Objekte nach dem Anhängen ändern, wird beim Aufrufen von SaveChanges der Wert des EntityKey verwendet, um die entsprechende Zeile zu aktualisieren (oder zu löschen), indem die entsprechende ID in der DB-Tabelle gefunden wird.

Mit der Attach-Methode können Sie außerdem Beziehungen zwischen Entitäten definieren, die bereits im ObjectContext vorhanden sind, aber nicht wurde automatisch verbunden. Grundsätzlich besteht der Hauptzweck von Attach darin, Entitäten zu verbinden, die bereits an den ObjectContext angehängt sind und nicht neu sind, sodass Sie Attach nicht zum Anhängen von Entitäten verwenden können, deren EntityState hinzugefügt wurde. In diesem Fall müssen Sie Add () verwenden.

Nehmen wir zum Beispiel an, Ihre Entität Person hat eine Navigationseigenschaft mit dem Namen Addresses, die eine Sammlung von Address Entität ist. Nehmen wir an, Sie haben beide Objekte aus dem Kontext gelesen, aber sie sind nicht miteinander verwandt, und Sie möchten es so machen:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.PersonReference.Attach(existingPerson)
ctx.SaveChanges();
158
Morteza Manavi

Dies ist eine späte Antwort, aber es könnte anderen helfen, die dies finden.

Grundsätzlich kann eine "getrennte" Entität auftreten, wenn Sie eine Entität außerhalb des Gültigkeitsbereichs "using" manipulieren.

Employee e = null;

using (var ctx = new MyModelContainer())
{
     e = ctx.Employees.SingleOrDefault(emp => emp .....);
}

using (var ctx2 = new MyModelContainer())
{
     e; // This entity instance is disconnected from ctx2
}

Wenn Sie einen anderen Gültigkeitsbereich "using" eingeben, wird die Verbindung der Variablen "e" getrennt, da sie zum vorherigen Gültigkeitsbereich "using" gehört. Da der vorherige Gültigkeitsbereich "using" zerstört wird, wird die Verbindung von "e" getrennt.

So verstehe ich es.

28
TchiYuan

Dies ist ein Zitat aus Programming Entity Framework: DbContext

Wenn Sie Remove für eine Entität aufrufen, die nicht vom Kontext überwacht wird, wird eine InvalidOperationException ausgelöst. Das Entity Framework löst diese Ausnahme aus, da nicht klar ist, ob es sich bei der zu entfernenden Entität um eine vorhandene Entität handelt, die zum Löschen markiert werden soll, oder um eine neue Entität, die einfach ignoriert werden soll. Aus diesem Grund können wir nicht nur Entfernen verwenden, um eine getrennte Entität als Gelöscht zu markieren. wir müssen es zuerst anhängen .

private static void TestDeleteDestination()
{
    Destination canyon;
    using (var context = new BreakAwayContext())
    {
        canyon = (from d in context.Destinations
        where d.Name == "Grand Canyon"
        select d).Single();
    }
    DeleteDestination(canyon);
}
private static void DeleteDestination(Destination destination)
{
    using (var context = new BreakAwayContext())
    {
        context.Destinations.Attach(destination);
        context.Destinations.Remove(destination);
        context.SaveChanges();
    }
}

Die TestDeleteDestination-Methode simuliert eine Clientanwendung, die ein vorhandenes Ziel vom Server abruft und es dann an die DeleteDestination-Methode auf dem Server übergibt. Die DeleteDestination-Methode verwendet die Attach-Methode, um dem Kontext mitzuteilen, dass es sich um ein vorhandenes Ziel handelt. Anschließend wird mit der Remove-Methode das vorhandene Ziel zum Löschen registriert

7
Teoman shipahi