2013-02-21 11 views
8

元の値ではなくChangeTrackerから元のエンティティ自体を取得する方法はありますか? StateModifiedある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); 

しかし、これは非常に素晴らしいいないようだ、と私は私にはわからないことに問題があると確信しています〜についてもっと良い方法がありますか?

私は文脈からDbContextか、単にアクセスChangeTrackerのオーバーライドSaveChanges Entity Frameworkの6.

答えて

18

を使用しています:

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

+0

@Eric元のプロパティ値を持つエンティティオブジェクトが必要ですか? –

+0

はい、そうです。おそらく、元の値のセットを与えられたエンティティを構築する方法... – Eric

1

は私がマテリアにクローンエンティティを提案し、あなたがそれを必要とする場合(全体元のオブジェクトグラフを維持するために、第2のコンテキストにそれらを添付しますもちろん)。あなたは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。私はこの問題を抱え、古いものを取得するために多くの時間を費やしました。まず、完全に切断されたオブジェクトを返そうとしました。それは更新中にそれ自身の問題のセットを持っていました。これは動作しますが、もう少しのシナリオをテストする必要があります。 –

+0

ちょっと@Clement。これはナビゲーション特性を水和させません。どんな手掛かり? –

+0

わかりません、私はnavプロパティでテストしていません。 Activator.CreateInstanceを使用しているため、(EFで生成されたランタイムプロキシタイプに依存しているため)ナビゲーションプロパティの遅延ロードが機能するとは思われません。あなたはそれらを処理するためにこのコードを変更することができるかもしれません... – Clement

-1

EF 6での作業中に、私は

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

ObjectContext.GetObjectType、プロキシタイプから基礎となるPOCOエンティティタイプを取得するには、次のコードを使用します。戻り代理オブジェクトからのPOCO

+0

これは型を返すだけです。私は元の値を得ることができませんでした。 –

関連する問題