Как получить оригинальную Entity из ChangeTracker

.net c# entity-framework entity-framework-6

Вопрос

Есть ли способ получить исходную сущность из ChangeTracker (а не только исходные значения)?

Если State Modified , то, полагаю, я мог бы это сделать:

// 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);

Но это не кажется очень приятным, и я уверен, что с ним проблемы, о которых я не знаю ... Есть ли лучший способ?

Я использую Entity Framework 6.

Принятый ответ

Переопределить SaveChanges из DbContext или просто получить доступ к ChangeTracker из контекста:

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

Вот метод, который создаст новый объект с исходными значениями. Таким образом, все сущности должны иметь бездонный публичный конструктор, вы можете просто построить экземпляр с new :

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;
}

Популярные ответы

Ницца. Вот немного модифицированная версия, которая будет обрабатывать сложные свойства:

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));
    }


Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему