2013-02-21 87 views
8

有沒有辦法從ChangeTracker(而不是原始值)獲取原始實體本身?如何從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.

回答

18

的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; 
} 
+0

我可能缺少一個微妙的東西,但我相信我知道如何做到這一點(這只是獲得原始值,對嗎?)我想要一個實際的強類型表示的原始實體 - 而不僅僅是原始值。 – Eric 2013-02-21 21:37:49

+0

@Eric你想擁有原始屬性值的實體對象? – 2013-02-21 21:39:14

+0

是的,這是正確的。也許一種方法來建立一個給定的一組原始值... – Eric 2013-02-21 21:40:06

1

我將在物化表明克隆實體,並將其連接到第二方面,保持整個原始對象圖(如果你需要它當然)。您可以通過修改T4模板將它們全部設置爲ICloneable。

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

謝謝@Clement。我有這個問題,並花了很多時間來得到舊的..首先嚐試返回完全斷開連接的對象。它在更新時有它自己的一套問題。這一個工程,需要測試一些更多的場景,雖然 – 2013-10-16 16:36:14

+0

嘿@Clement。這個不會滋潤導航屬性。任何線索? – 2013-10-16 16:55:54

+0

不確定,我還沒有用導航屬性進行測試。因爲它使用Activator.CreateInstance,所以我不希望導航屬性延遲加載工作(因爲它依賴於由EF生成的運行時代理類型)。您可能可以更改此代碼來處理它們... – Clement 2013-10-16 21:53:24

-1

雖然與EF 6個工作我用下面的代碼從代理型底層POCO實體類型,

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

ObjectContext.GetObjectType:返回來自代理對象的POCO

+0

這隻返回一個類型。我無法獲得原始值。 – 2015-09-10 00:21:34