C# 如何从ChangeTracker获取原始实体

C# 如何从ChangeTracker获取原始实体,c#,.net,entity-framework,entity-framework-6,C#,.net,Entity Framework,Entity Framework 6,是否有办法从ChangeTracker获取原始实体本身(而不仅仅是原始值) 如果状态是修改的,那么我想我可以这样做: // Get the DbEntityEntry from the DbContext.ChangeTracker... // Store the current values var currentValues = entry.CurrentValues.Clone(); // Set to the original values entry.CurrentValues.S

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

如果
状态
修改的
,那么我想我可以这样做:

// 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。

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

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

很好。下面是一个稍加修改的版本,它将处理复杂的属性:

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));
    }
publicstatictenty-GetOriginal(这个DbContext-ctx,tenty-updatedEntity),其中TEntity:class
{
Func getOriginal=null;
getOriginal=(原始值,类型)=>
{
object original=Activator.CreateInstance(类型,true);
foreach(原始值中的var ptyName.PropertyName)
{
var property=type.GetProperty(ptyName);
对象值=原始值[ptyName];
if(值为DbPropertyValues)//嵌套的复杂对象
{
SetValue(original,getOriginal(值为DbPropertyValues,property.PropertyType));
}
其他的
{
property.SetValue(原始,值);
}
}
归还原件;
};
return(tenty)getOriginal(ctx.Entry(updatedEntity).originalvalue,typeof(tenty));
}

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

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

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

我可能缺少一个细节,但我相信我知道如何做到这一点(这只是获取原始值,对吗?)我需要原始实体的实际强类型表示,而不仅仅是原始值。@Eric您想要具有原始属性值的实体对象吗?是的,这是正确的。也许是一种在给定一组原始值的情况下构造实体的方法…@Eric done,我编写了一个方法,该方法通过ReflectionTanks@Clement创建实体并设置属性值。我遇到了这个问题,花了很多时间来获取旧的。首先,我尝试返回完全断开连接的对象。但它在更新时也有自己的问题。这一个有效,需要测试更多的场景thoughHey@Clement。这一个不具有导航属性。有什么线索吗?不确定,我还没有测试过导航属性。因为它使用的是Activator.CreateInstance,所以我不希望延迟加载导航属性(因为它依赖于EF生成的运行时代理类型)。您可以更改此代码来处理它们…谢谢@Clement。我一次加载一个图表,但没有修改以一般方式填充导航属性。这只返回一个类型。我无法获得原始值。
var entityType = ObjectContext.GetObjectType(dbEntitymodifiedEntry.Entity.GetType());