2013-02-21 9 views
8

Gibt es eine Möglichkeit, die ursprüngliche Entität selbst aus der ChangeTracker (anstatt nur die ursprünglichen Werte) zu erhalten?So erhalten Sie die ursprüngliche Entität von ChangeTracker

Wenn die StateModified ist, dann nehme ich an, ich könnte dies tun:

// Get the DbEntityEntry from the DbContext.ChangeTracker... 

// Store the current values 
var currentValues = entry.CurrentValues.Clone(); 

// Set to the original values 
entry.CurrentValues.SetValues(entry.OriginalValues.Clone()); 

// Now we have the original entity 
Foo entity = (Foo)entry.Entity; 

// Do something with it... 

// Restore the current values 
entry.CurrentValues.SetValues(currentValues); 

Aber dies scheint nicht sehr schön, und ich bin sicher, es gibt Probleme mit ihm, dass ich nicht weiß, über ... Gibt es einen besseren Weg?

ich Entity Framework bin mit 6.

Antwort

18

Aufschalten SaveChanges von DbContext oder Zugriff nur ChangeTracker aus dem Kontext:

foreach (var entry in context.ChangeTracker.Entries<Foo>()) 
{ 
    if (entry.State == System.Data.EntityState.Modified) 
    { 
     // use entry.OriginalValues 
     Foo originalFoo = CreateWithValues<Foo>(entry.OriginalValues); 
    } 
} 

Hier ist eine Methode, die eine neue Einheit mit dem schaffen ursprüngliche Werte. So werden alle Einheiten einen parameter öffentlichen Konstruktor haben sollten, können Sie einfach eine Instanz mit new konstruieren:

private T CreateWithValues<T>(DbPropertyValues values) 
    where T : new() 
{ 
    T entity = new T(); 
    Type type = typeof(T); 

    foreach (var name in values.PropertyNames) 
    { 
     var property = type.GetProperty(name); 
     property.SetValue(entity, values.GetValue<object>(name)); 
    } 

    return entity; 
} 
+0

Ich vermisse eine Feinheit, aber ich glaube, ich weiß, wie dies zu tun (das ist nur die ursprünglichen Werte, oder?) Ich möchte eine tatsächliche stark typisierte Darstellung der ursprünglichen Entität - nicht nur die ursprünglichen Werte. – Eric

+0

@Eric Sie wollen Entity-Objekt mit ursprünglichen Eigenschaften Werte? –

+0

Ja, das ist richtig. Vielleicht eine Möglichkeit, eine Entität mit einer Reihe von ursprünglichen Werten zu konstruieren ... – Eric

1

Ich würde Klon Einheiten auf Materialisierung vorschlagen und legen sie auf den zweiten Kontext ganze Originalobjekte Graph zu halten (wenn Sie es brauchen Na sicher). Sie können alle ICloneable durch Ändern der T4-Vorlage machen.

5

Schön. Hier ist eine leicht modifizierte Version, die komplexen Eigenschaften behandelt:

public static TEntity GetOriginal<TEntity>(this DbContext ctx, TEntity updatedEntity) where TEntity : class 
    { 
     Func<DbPropertyValues, Type, object> getOriginal = null; 
     getOriginal = (originalValues, type) => 
      { 
       object original = Activator.CreateInstance(type, true); 
       foreach (var ptyName in originalValues.PropertyNames) 
       { 
        var property = type.GetProperty(ptyName); 
        object value = originalValues[ptyName]; 
        if (value is DbPropertyValues) //nested complex object 
        { 
         property.SetValue(original, getOriginal(value as DbPropertyValues, property.PropertyType)); 
        } 
        else 
        { 
         property.SetValue(original, value); 
        } 
       } 
       return original; 
      }; 
     return (TEntity)getOriginal(ctx.Entry(updatedEntity).OriginalValues, typeof(TEntity)); 
    } 
+0

Danke @Clement. Ich hatte dieses Problem und verbrachte viel Zeit, um die alten zu bekommen. Zuerst versuchte, völlig getrennte Objekte zurückzugeben. Es hatte seinen eigenen Problemsatz während der Aktualisierung. Dieser funktioniert, muss einige weitere Szenarien obwohl –

+0

Hey @Clement testen. Dieser hydratisiert die Navigationseigenschaften nicht. Irgendeine Ahnung? –

+0

Nicht sicher, ich habe nicht mit Nav-Eigenschaften getestet. Da Activator.CreateInstance verwendet wird, erwarte ich nicht, dass das verzögerte Laden von Navigationseigenschaften funktioniert (da es auf einem Laufzeit-Proxy-Typ beruht, der von EF generiert wird). Sie können möglicherweise diesen Code ändern, um sie zu behandeln ... – Clement

-1

Während der Arbeit mit EF 6 i den folgenden Code verwendet, um den zugrunde liegenden POCO Entitätstyp von Proxy-Typ zu erhalten,

var entityType = ObjectContext.GetObjectType(dbEntitymodifiedEntry.Entity.GetType()); 

ObjectContext.GetObjectType: Zurück die POCO von Proxy-Objekt

+0

Dies gibt nur einen Typ zurück. Ich konnte die ursprünglichen Werte nicht erhalten. –

Verwandte Themen