2013-02-21 3 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); 

그러나 이것은 아주 좋은하지 않는 것, 그리고 내가 모르는 그것으로 문제가 확실 해요 ... 더 좋은 방법 있니?

내가 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); 
    } 
} 

하면 가진 새로운 개체를 생성하는 방법 원래 값. 따라서 모든 엔티티는 매개 변수가없는 public 생성자가 있어야합니다, 당신은 단순히 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

내가 구체화에 복제 엔티티를 제안하고 당신이 그것을 필요로하는 경우에 (전체 원래 개체 그래프를 유지하기 위해 두 번째 상황에 첨부 할 당연하지). T4 템플릿을 수정하여 ICloneable로 만들 수 있습니다.

5

니스 내가 프록시 유형에서 기본 POCO 엔티티 유형을 얻기 위해 다음 코드를 사용

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

Thanks @Clement. 나는이 문제가 있었고 오래된 것들을 얻기 위해 많은 시간을 보냈다. 처음에는 완전히 연결이 끊어진 물건을 돌려 주려고했다. 그것을 업데이 트하는 동안 문제의 자체 세트를 했어. 이 하나의 작품, 비록 더 많은 시나리오를 테스트 할 필요가 –

+0

안녕하세요 @Clement. 이것은 항행 속성을 수화하지 않습니다. 어떤 단서? –

+0

잘 모르지만 nav 속성을 테스트하지 않았습니다. Activator.CreateInstance를 사용하기 때문에 탐색 속성을 느리게 로딩 할 필요가 없습니다 (EF에서 생성 한 런타임 프록시 유형에 의존하므로). 당신이 그들을 처리하기 위해이 코드를 변경할 수 있습니다 ... – Clement

-1

EF 6 작업하는 동안,

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

ObjectContext.GetObjectType : 여기에 복잡한 속성을 처리 할 약간 수정 된 버전입니다 반환 프록시 객체의 POCO

+0

이것은 형식을 반환합니다. 나는 원래의 가치를 얻을 수 없었다. –

관련 문제