DbContext和RejectChanges

时间:2012-05-10 13:47:48

标签: entity-framework

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

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

5 个答案:

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

  • 放弃更改的数据并重新加载整个数据集(通过重新创建上下文)
  • 将此逻辑分离为不能处理实时数据,仅在确认修改后才将数据修改推送到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();
}