web-dev-qa-db-de.com

DbSet.Attach (Entität) vs DbContext.Entry (Entität) .State = EntityState.Modified

Wenn ich mich in einem getrennten Szenario befinde und ein dto vom Client erhalte, das ich einer Entität zum Speichern zuordnen kann, gehe ich folgendermaßen vor:

context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();

Wofür ist dann die DbSet.Attach(entity)

oder warum sollte ich die .Attach-Methode verwenden, wenn EntityState.Modified die Entität bereits anfügt?

99
Elisabeth

Wenn Sie context.Entry(entity).State = EntityState.Modified; ausführen, fügen Sie die Entität nicht nur dem DbContext hinzu, sondern markieren auch die gesamte Entität als fehlerhaft. Dies bedeutet, dass EF beim Ausführen von context.SaveChanges() eine Update-Anweisung generiert, die aktualisiert all die Felder der Entität.

Dies ist nicht immer erwünscht.

Andererseits fügt DbSet.Attach(entity) die Entität dem Kontext hinzu without und markiert sie als verschmutzt. Es ist äquivalent zu context.Entry(entity).State = EntityState.Unchanged;

Wenn Sie auf diese Weise eine Verbindung herstellen, generiert EF beim nächsten Aufruf von context.SaveChanges() keine Datenbankaktualisierung für diese Entität, es sei denn, Sie aktualisieren anschließend eine Eigenschaft für die Entität.

Selbst wenn Sie vorhaben, eine Entität zu aktualisieren, wenn die Entität viele Eigenschaften (DB-Spalten) hat, Sie aber nur einige aktualisieren möchten, ist es möglicherweise von Vorteil, eine DbSet.Attach(entity) auszuführen. und aktualisieren Sie dann nur die wenigen Eigenschaften, die aktualisiert werden müssen. Auf diese Weise wird eine effizientere Update-Anweisung von EF generiert. EF aktualisiert nur die Eigenschaften, die Sie geändert haben (im Gegensatz zu context.Entry(entity).State = EntityState.Modified;, wodurch alle Eigenschaften/Spalten aktualisiert werden).

Relevante Dokumentation: Add/Attach und Entity States .

Codebeispiel

Angenommen, Sie haben die folgende Entität:

public class Person
{
    public int Id { get; set; } // primary key
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Wenn Ihr Code so aussieht:

context.Entry(personEntity).State = EntityState.Modified;
context.SaveChanges();

Die generierte SQL sieht ungefähr so ​​aus:

UPDATE person
SET FirstName = 'whatever first name is',
    LastName = 'whatever last name is'
WHERE Id = 123; -- whatever Id is.

Beachten Sie, wie die obige Update-Anweisung alle Spalten aktualisiert, unabhängig davon, ob Sie die Werte tatsächlich geändert haben oder nicht.

Im Gegensatz dazu, wenn Ihr Code den "normalen" Anhang wie folgt verwendet:

context.People.Attach(personEntity); // State = Unchanged
personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty.
context.SaveChanges();

Dann ist die generierte Update-Anweisung anders:

UPDATE person
SET FirstName = 'John'
WHERE Id = 123; -- whatever Id is.

Wie Sie sehen können, aktualisiert die update-Anweisung only die Werte, die tatsächlich geändert wurden, nachdem Sie die Entität an die angefügt haben Kontext. Abhängig von der Struktur Ihrer Tabelle kann sich dies positiv auf die Leistung auswirken.

Welche Option für Sie besser ist, hängt ganz davon ab, was Sie tun möchten.

248
sstan

Wenn Sie das DbSet.Update -Methode markiert Entity Framework alle Eigenschaften Ihrer Entität als EntityState.Modified, so verfolgt sie. Wenn Sie nur einige Ihrer Eigenschaften ändern möchten, aber nicht alle, verwenden Sie DbSet.Attach. Diese Methode macht alle Ihre Eigenschaften EntityState.Unchanged, also müssen Sie Ihre Eigenschaften festlegen, die Sie aktualisieren möchten EntityState.Modified. Also, wenn die App auf DbContext.SaveChanges, es werden nur geänderte Eigenschaften bearbeitet.

0
Orhun