11

有没有办法从ChangeTracker(而不仅仅是原始值)获取原始实体本身?

如果StateModified,那么我想我可以这样做:

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

但这似乎不太好,而且我确定它存在我不知道的问题......有没有更好的方法?

我正在使用实体框架 6。

4

4 回答 4

23

覆盖SaveChangesDbContext 或仅从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;
}
于 2013-02-21T21:34:14.570 回答
5

好的。这是一个稍微修改过的版本,可以处理复杂的属性:

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));
    }
于 2013-08-14T11:32:01.110 回答
1

我建议在物化上克隆实体并将它们附加到第二个上下文以保留整个原始对象图(当然,如果你需要它)。您可以通过修改 T4 模板使它们都 ICloneable。

于 2013-02-22T11:52:11.193 回答
-1

在使用 EF 6 时,我使用以下代码从代理类型获取底层 POCO 实体类型,

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

ObjectContext.GetObjectType: 从代理对象返回 POCO

于 2015-04-30T15:08:18.487 回答