896 Stimmen

Entity Framework 5 Aktualisieren eines Datensatzes

Ich habe verschiedene Methoden zum Bearbeiten/Aktualisieren eines Datensatzes innerhalb von Entity Framework 5 in einer ASP.NET MVC3-Umgebung untersucht, aber bisher erfüllt keine von ihnen alle Anforderungen, die ich habe. Ich werde erklären, warum.

Ich habe drei Methoden gefunden, zu denen ich die Vor- und Nachteile nennen werde:

Methode 1 - Originaldatensatz laden, jede Eigenschaft aktualisieren

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    original.BusinessEntityId = updatedUser.BusinessEntityId;
    original.Email = updatedUser.Email;
    original.EmployeeId = updatedUser.EmployeeId;
    original.Forename = updatedUser.Forename;
    original.Surname = updatedUser.Surname;
    original.Telephone = updatedUser.Telephone;
    original.Title = updatedUser.Title;
    original.Fax = updatedUser.Fax;
    original.ASPNetUserId = updatedUser.ASPNetUserId;
    db.SaveChanges();
}    

Profis

  • Kann angeben, welche Eigenschaften sich ändern
  • Ansichten müssen nicht jede Eigenschaft enthalten

Nachteile

  • 2 x Abfragen der Datenbank, um das Original zu laden und dann zu aktualisieren

Methode 2 - Originaldatensatz laden, geänderte Werte einstellen

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    db.Entry(original).CurrentValues.SetValues(updatedUser);
    db.SaveChanges();
}

Profis

  • Nur geänderte Eigenschaften werden an die Datenbank gesendet

Nachteile

  • Ansichten müssen jede Eigenschaft enthalten
  • 2 x Abfragen der Datenbank, um das Original zu laden und dann zu aktualisieren

Methode 3 - Aktualisierten Datensatz anhängen und Status auf EntityState.Modified setzen

db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();

Profis

  • 1 x Abfrage der Datenbank zur Aktualisierung

Nachteile

  • Kann nicht angeben, welche Eigenschaften sich ändern
  • Ansichten müssen jede Eigenschaft enthalten

Pregunta

Meine Frage an euch: Gibt es einen sauberen Weg, wie ich diese Ziele erreichen kann?

  • Kann angeben, welche Eigenschaften sich ändern
  • Ansichten müssen nicht jede Eigenschaft enthalten (z. B. das Passwort!)
  • 1 x Abfrage der Datenbank zur Aktualisierung

Mir ist klar, dass dies nur eine Kleinigkeit ist, aber vielleicht übersehe ich eine einfache Lösung für dieses Problem. Wenn nicht, wird sich Methode eins durchsetzen ;-)

688voto

Ladislav Mrnka Punkte 355028

Sie suchen nach:

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();

176voto

smd Punkte 1933

Die akzeptierte Antwort gefällt mir sehr gut. Ich glaube, es gibt auch noch eine andere Möglichkeit, dies zu tun. Nehmen wir an, Sie haben eine sehr kurze Liste von Eigenschaften, die Sie niemals in eine Ansicht aufnehmen möchten, so dass diese beim Aktualisieren der Entität ausgelassen werden. Nehmen wir an, dass diese beiden Felder Passwort und SSN sind.

db.Users.Attach(updatedUser);

var entry = db.Entry(updatedUser);
entry.State = EntityState.Modified;

entry.Property(e => e.Password).IsModified = false;
entry.Property(e => e.SSN).IsModified = false;   

db.SaveChanges();   

In diesem Beispiel können Sie Ihre Geschäftslogik im Wesentlichen in Ruhe lassen, nachdem Sie ein neues Feld zu Ihrer Tabelle "Benutzer" und zu Ihrer Ansicht hinzugefügt haben.

28voto

Stefano Camisassi Punkte 284
foreach(PropertyInfo propertyInfo in original.GetType().GetProperties()) {
    if (propertyInfo.GetValue(updatedUser, null) == null)
        propertyInfo.SetValue(updatedUser, propertyInfo.GetValue(original, null), null);
}
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();

25voto

Ian Warburton Punkte 14158

Ich habe eine zusätzliche Aktualisierungsmethode zu meiner Repository-Basisklasse hinzugefügt, die der von Scaffolding generierten Aktualisierungsmethode ähnelt. Anstatt das gesamte Objekt auf "modifiziert" zu setzen, setzt sie eine Reihe von individuellen Eigenschaften. (T ist ein generischer Parameter der Klasse.)

public void Update(T obj, params Expression<Func<T, object>>[] propertiesToUpdate)
{
    Context.Set<T>().Attach(obj);

    foreach (var p in propertiesToUpdate)
    {
        Context.Entry(obj).Property(p).IsModified = true;
    }
}

Und dann anrufen, zum Beispiel:

public void UpdatePasswordAndEmail(long userId, string password, string email)
{
    var user = new User {UserId = userId, Password = password, Email = email};

    Update(user, u => u.Password, u => u.Email);

    Save();
}

Ich mag eine Reise zur Datenbank. Es ist wahrscheinlich besser, dies mit Ansichtsmodellen zu tun, obwohl, um zu vermeiden, wiederholte Sätze von Eigenschaften. Ich habe das noch nicht gemacht, weil ich nicht weiß, wie ich vermeiden kann, die Validierungsmeldungen meiner View Model Validators in mein Domain-Projekt zu bringen.

11voto

public interface IRepository
{
    void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class;
}

public class Repository : DbContext, IRepository
{
    public void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class
    {
        Set<T>().Attach(obj);
        propertiesToUpdate.ToList().ForEach(p => Entry(obj).Property(p).IsModified = true);
        SaveChanges();
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X