我正在使用 RIA 服务,其中 ObjectContext 具有 RejectChanges() 方法。但是,我现在正在桌面应用程序中使用 EF 4.4,但找不到该方法。所以,我的问题是:在我允许用户对集合进行批量 CrUD 操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但如果我需要将更改恢复为 1-2 个实体,这听起来非常不必要。
那么,拒绝更改的最佳方法是什么?而且,我们如何知道上下文是否正在做某事(IsBusy)?
我正在使用 RIA 服务,其中 ObjectContext 具有 RejectChanges() 方法。但是,我现在正在桌面应用程序中使用 EF 4.4,但找不到该方法。所以,我的问题是:在我允许用户对集合进行批量 CrUD 操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但如果我需要将更改恢复为 1-2 个实体,这听起来非常不必要。
那么,拒绝更改的最佳方法是什么?而且,我们如何知道上下文是否正在做某事(IsBusy)?
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 在后面执行其逻辑以在执行更改时保持数据一致,但稍后您决定不会保存这些更改. 在这种情况下,您应该执行以下操作之一:
如果你说它做某事,上下文就是做某事。它本身永远不会变得忙碌。
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;
}
}
}
}
我知道这是一个老问题。但是,没有一个答案适合我的情况。我需要拒绝对集合中仅 1 个实体的更改。这对我有用:
var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext;
objectContext.Refresh(RefreshMode.StoreWins, partMaster);
这对我有用:
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 在这种情况下
这可能是一个旧答案,但对任何新访问者都很有用...... Reload 函数将从数据源重新加载对象并覆盖任何现有更改,并且新加载的实体将具有未更改的状态。
public static void UndoEntityChanges(object Entity)
{
<EFModelContainer>.Entry(Entity).Reload();
}