我正在使用RIA服务,其中ObjectContext具有RejectChanges()方法。但是,我现在正在桌面应用程序中使用EF 4.4,我找不到该方法。所以,我的问题是:在我允许用户对收集进行批量CrUD操作的场景中,如何恢复所有更改?我可以继续重新创建Context并再次获取数据,但如果我需要将更改还原为1-2个实体,那么这听起来非常不必要。
那么,拒绝变更的最佳方法是什么?而且,我们如何知道上下文是否正在做某事(IsBusy)?
答案 0 :(得分:12)
EF没有任何直接的“拒绝更改”操作。您可以浏览ChangeTracker
/ ObjectStateManager
中的实体条目,并使用修改后实体的原始值覆盖当前值。您还可以分离添加的实体并将已删除的实体更改回未更改但仅当您(或内部EF)未更改任何独立关联(关系)的状态时,所有实体才会起作用。如果你也处理关系,整个事情会变得复杂得多,因为你必须恢复关系 - 在这种情况下,重新加载数据会更简单。
要恢复DbContext API中的更改,您可以尝试:
foreach (var entry in context.ChangeTracker
.Entries<YourEntityType>()
.Where(e => e.State == EntityState.Modified))
{
entry.CurrentValues.SetValues(entry.OriginalValues);
}
在这种情况下,我认为主要的问题是你如何使用实体 - 你允许对实时数据进行更改,而EF会在后面执行逻辑,以便在执行更改时保持数据的一致性,但稍后您决定这些更改将会不被保存。在这种情况下,您应该执行以下操作之一:
如果你说要做某事,语境正在做某事。它永远不会变得忙碌。
答案 1 :(得分:11)
public void RejectChanges()
{
foreach (var entry in ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Modified:
{
entry.CurrentValues.SetValues(entry.OriginalValues);
entry.State = EntityState.Unchanged;
break;
}
case EntityState.Deleted:
{
entry.State = EntityState.Unchanged;
break;
}
case EntityState.Added:
{
entry.State = EntityState.Detached;
break;
}
}
}
}
答案 2 :(得分:2)
我知道这是一个老问题。但是,没有一个答案符合我的情况。我需要拒绝集合中只有1个实体的更改。这对我有用:
var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext;
objectContext.Refresh(RefreshMode.StoreWins, partMaster);
答案 3 :(得分:1)
这对我有用:
public void RejectChanges() {
var context = ((IObjectContextAdapter)this).ObjectContext;
foreach (var change in this.ChangeTracker.Entries()) {
if (change.State == EntityState.Modified) {
context.Refresh(RefreshMode.StoreWins, change.Entity);
}
if (change.State == EntityState.Added) {
context.Detach(change.Entity);
}
}
}
this =这种情况下的DbContext
答案 4 :(得分:0)
这可能是一个旧答案,但对任何新访客都有用.... 重载函数将从数据源重新加载对象并覆盖任何现有更改,新加载的实体将保持不变状态。
public static void UndoEntityChanges(object Entity)
{
<EFModelContainer>.Entry(Entity).Reload();
}