이것은 사소한 질문 일 수 있지만 : ADO.NET 엔터티 프레임 워크가 자동으로 변경 사항 (생성 된 엔터티에서)을 추적하고 따라서 원래 값을 유지하므로 엔터티 개체에 대한 변경 사항을 롤백 할 수있는 방법은 무엇입니까?
사용자가 그리드보기에서 “고객”엔터티 집합을 편집 할 수있는 양식이 있습니다.
이제 “수락”과 “되돌리기”버튼이 두 개 있습니다. “수락”을 클릭하면 호출 Context.SaveChanges()
하면 변경된 개체가 데이터베이스에 다시 기록됩니다. “되돌리기”를 클릭하면 모든 개체가 원래 속성 값을 가져 오기를 원합니다. 그 코드는 무엇입니까?
감사
답변
EF에는 되돌리기 또는 변경 취소 작업이 없습니다. 각 엔티티가 ObjectStateEntry
에서 ObjectStateManager
. 상태 항목에는 원래 값과 실제 값이 포함되어 있으므로 원래 값을 사용하여 현재 값을 덮어 쓸 수 있지만 각 엔터티에 대해 수동으로 수행해야합니다. 탐색 속성 / 관계의 변경 사항을 무시하지 않습니다.
“변경 사항을 되 돌리는”일반적인 방법은 컨텍스트를 삭제하고 엔티티를 다시로드하는 것입니다. 다시로드하지 않으려면 엔티티의 복제본을 만들고 새 개체 컨텍스트에서 해당 복제본을 수정해야합니다. 사용자가 변경 사항을 취소해도 원래 엔티티가 유지됩니다.
답변
DbContext의 ChangeTracker에서 더티 항목을 쿼리합니다. 삭제 된 항목 상태를 변경되지 않음으로 설정하고 추가 된 항목을 분리됨으로 설정합니다. 수정 된 항목의 경우 원래 값을 사용하고 항목의 현재 값을 설정하십시오. 마지막으로 수정 된 항목의 상태를 변경되지 않음으로 설정합니다.
public void RollBack()
{
var context = DataContextFactory.GetDataContext();
var changedEntries = context.ChangeTracker.Entries()
.Where(x => x.State != EntityState.Unchanged).ToList();
foreach (var entry in changedEntries)
{
switch(entry.State)
{
case EntityState.Modified:
entry.CurrentValues.SetValues(entry.OriginalValues);
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
case EntityState.Deleted:
entry.State = EntityState.Unchanged;
break;
}
}
}
답변
dbContext.Entry(entity).Reload();
MSDN에 동의 :
데이터베이스의 값으로 속성 값을 덮어 쓰는 데이터베이스에서 엔터티를 다시로드합니다. 이 메서드를 호출 한 후 엔티티는 Unchanged 상태가됩니다.
요청을 통해 데이터베이스로 되 돌리면 몇 가지 단점이 있습니다.
- 네트워크 트래픽
- DB 과부하
- 증가 된 애플리케이션 응답 시간
답변
이것은 나를 위해 일했습니다.
dataContext.customer.Context.Refresh(RefreshMode.StoreWins, item);
item
되돌릴 고객 엔티티는 어디에 있습니까 ?
답변
변경 사항을 추적하지 않는 쉬운 방법. 모든 엔티티를 보는 것보다 더 빠릅니다.
public void Rollback()
{
dataContext.Dispose();
dataContext= new MyEntities(yourConnection);
}
답변
// Undo the changes of all entries.
foreach (DbEntityEntry entry in context.ChangeTracker.Entries())
{
switch (entry.State)
{
// Under the covers, changing the state of an entity from
// Modified to Unchanged first sets the values of all
// properties to the original values that were read from
// the database when it was queried, and then marks the
// entity as Unchanged. This will also reject changes to
// FK relationships since the original value of the FK
// will be restored.
case EntityState.Modified:
entry.State = EntityState.Unchanged;
break;
case EntityState.Added:
entry.State = EntityState.Detached;
break;
// If the EntityState is the Deleted, reload the date from the database.
case EntityState.Deleted:
entry.Reload();
break;
default: break;
}
}
그것은 나를 위해 일했습니다. 그러나 이전 데이터를 가져 오려면 컨텍스트에서 데이터를 다시로드해야합니다. 여기에 소스
답변
“이것은 나를 위해 일했습니다.
dataContext.customer.Context.Refresh(RefreshMode.StoreWins, item);
item
되돌릴 고객 엔티티는 어디에 있습니까 ? “
SQL Azure에서 ObjectContext.Refresh를 사용하여 테스트를 수행했으며 “RefreshMode.StoreWins”는 각 엔터티에 대한 데이터베이스에 대한 쿼리를 실행하고 성능 누수를 유발합니다. Microsoft 설명서 ()를 기반으로 :
ClientWins : 개체 컨텍스트의 개체에 대한 속성 변경 사항이 데이터 소스의 값으로 대체되지 않습니다. 다음에 SaveChanges를 호출하면 이러한 변경 사항이 데이터 소스로 전송됩니다.
StoreWins : 개체 컨텍스트의 개체에 대한 속성 변경 사항이 데이터 소스의 값으로 바뀝니다.
.SaveChanges를 실행하면 데이터 소스에 “삭제 된”변경 사항이 커밋되기 때문에 ClientWins도 좋은 아이디어가 아닙니다.
생성 된 새 컨텍스트에서 쿼리를 실행하려고 할 때 컨텍스트를 삭제하고 새 컨텍스트를 만들면 “기본 공급자가 열릴 때 실패했습니다”라는 메시지와 함께 예외가 발생하기 때문에 아직 최선의 방법이 무엇인지 모르겠습니다.
문안 인사,
Henrique Clausing
