Entity framework DbContext和RejectChanges

Entity framework DbContext和RejectChanges,entity-framework,Entity Framework,我使用的是RIA服务,其中ObjectContext具有RejectChanges()方法。但是,我现在正在桌面应用程序中使用EF4.4,我找不到该方法。所以,我的问题是:在允许用户对集合执行批处理CrUD操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但是如果我需要将更改恢复到1-2个实体,那么这听起来是非常不必要的 那么,拒绝更改的最佳方式是什么?另外,我们如何知道上下文是否正在做某事(IsBusy)?EF没有任何直接的“拒绝更改”操作。您可以浏览ChangeTrac

我使用的是RIA服务,其中ObjectContext具有RejectChanges()方法。但是,我现在正在桌面应用程序中使用EF4.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);
}
foreach(context.ChangeTracker中的var条目
.条目()
.Where(e=>e.State==EntityState.Modified))
{
entry.CurrentValues.SetValues(entry.OriginalValues);
}
在这种情况下,我认为主要的问题是您如何处理实体-您允许对实时数据进行更改,EF在执行更改时在后台执行其逻辑以保持数据一致,但稍后您决定不保存这些更改。在这种情况下,您应该执行以下操作之一:

  • 放弃更改的数据并重新加载整个数据集(通过重新创建上下文)
  • 将此逻辑分离,使其不在实时数据上工作,并仅在确认修改后才将数据修改推送到EF上下文
如果你说它是为了做某事,那么上下文就是在做某事。它本身从不忙碌。

这对我来说很有用:

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在这种情况下

我知道这是一个老问题。然而,没有一个答案适合我的情况。我只需要拒绝集合中1个实体上的更改。这就是我的工作原理:

    var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext;
    objectContext.Refresh(RefreshMode.StoreWins, partMaster);

这可能是一个古老的答案,但对任何新访客都很有用。。。。 “重新加载”功能将从数据源重新加载对象并覆盖任何现有更改,新加载的实体将具有未更改的状态

public static void UndoEntityChanges(object Entity)
{
    <EFModelContainer>.Entry(Entity).Reload();
}
公共静态void UndoEntityChanges(对象实体)
{
.Entry(Entity.Reload();
}

重新创建上下文将是一个很好的解决方案。但是,我在同步相关数据方面遇到了问题。例如,我在ViewA的CollectionA上有CRUD,在ViewB的COllectionB上有CRUD。CollectionB还引用CollectionA。所以,如果我有两个上下文对象,分别用于CollectionA和CollectionB,如果我在ViewA上更改CollectionA,我将如何同步ViewB?当有一个上下文时,所有内容都是同步的,因为我们实际上只处理一个实例集合,而不是两个实例集合。重新创建“全局”上下文会造成混乱。:)我使用“全局”上下文是否犯了错误?至于“忙”,我担心如果我在async maner中发出一个负载,然后尝试发出另一个负载,而之前没有完成,会发生什么?通过这种方式,我可以检查它是否“忙”,这样我就可以排队等待新的负载。+1用于注意大多数人似乎错过了什么。关系:可以通过查看State的Entries集合来跟踪无法获取的更改!=不变。(EF v6.)删除的实体如何?另外,对于被其他用户(而不是您)更改的实体,您将如何获取新数据?虽然问题是关于集合更改,而不是单个实体,但我不知道这些答案对您有何帮助?你上面的答案(soul75)与你的建议完全相同,只是它对集合中的所有项目都适用。戈兰,如果集合中的所有更改都被拒绝,那么我的数据将无效。集合中只有一项需要还原为原始值。我需要更精细的方法。我知道有时候其他人也需要粒度控制。我发布这个答案是为了帮助其他有类似需求的人。好吧,你不使用foreach,但你基本上使用了相同的技术(使用StoreWins刷新),所以我看不到你的答案中的附加值,因为你刚刚删除了循环。这似乎是唯一一个在不影响数据库的情况下处理所有状态的答案+1如果我只更改参考资料怎么办?当没有任何外键属性受到影响时,特别是纯m:n?
public static void UndoEntityChanges(object Entity)
{
    <EFModelContainer>.Entry(Entity).Reload();
}