9

我正在使用 RIA 服务,其中 ObjectContext 具有 RejectChanges() 方法。但是,我现在正在桌面应用程序中使用 EF 4.4,但找不到该方法。所以,我的问题是:在我允许用户对集合进行批量 CrUD 操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但如果我需要将更改恢复为 1-2 个实体,这听起来非常不必要。

那么,拒绝更改的最佳方法是什么?而且,我们如何知道上下文是否正在做某事(IsBusy)?

4

5 回答 5

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 在后面执行其逻辑以在执行更改时保持数据一致,但稍后您决定不会保存这些更改. 在这种情况下,您应该执行以下操作之一:

  • 丢弃更改的数据并重新加载整个数据集(通过重新创建上下文)
  • 将此逻辑分离为不适用于实时数据并仅在真正确认修改时将数据修改推送到 EF 上下文

如果你说它做某事,上下文就是做某事。它本身永远不会变得忙碌。

于 2012-05-10T14:47:51.690 回答
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;
                        }
                }
            }
        }
于 2014-02-28T13:56:21.453 回答
2

我知道这是一个老问题。但是,没有一个答案适合我的情况。我需要拒绝对集合中仅 1 个实体的更改。这对我有用:

    var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext;
    objectContext.Refresh(RefreshMode.StoreWins, partMaster);
于 2014-01-20T22:47:04.320 回答
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 在这种情况下

于 2012-07-10T12:54:41.307 回答
0

这可能是一个旧答案,但对任何新访问者都很有用...... Reload 函数将从数据源重新加载对象并覆盖任何现有更改,并且新加载的实体将具有未更改的状态。

public static void UndoEntityChanges(object Entity)
{
    <EFModelContainer>.Entry(Entity).Reload();
}
于 2015-06-12T21:34:33.147 回答