如何从ChangeTracker获取原始实体
本文关键字:原始 实体 获取 ChangeTracker | 更新日期: 2023-09-27 18:00:40
有没有办法从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);
但这似乎不太好,我确信它有一些我不知道的问题。。。有更好的方法吗?
我使用的是实体框架6。
覆盖DbContext的SaveChanges
或仅从上下文访问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));
}
我建议在物化时克隆实体,并将它们附加到第二个上下文中,以保持整个原始对象的图形(当然,如果您需要的话)。您可以通过修改T4模板使它们全部ICloneable。
在使用EF 6时,我使用以下代码从代理类型中获取底层POCO实体类型
var entityType = ObjectContext.GetObjectType(dbEntitymodifiedEntry.Entity.GetType());
ObjectContext.GetObjectType
:从代理对象返回POCO