我正在使用RIA服务,其中ObjectContext具有RejectChanges()方法。但是,我现在正在使用EF 4.4在桌面应用程序中,并且找不到该方法。所以,我的问题是:在允许用户对collection进行批量CrUD操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但如果我需要将更改还原回1-2个实体,则这听起来非常不必要。DbContext和RejectChanges
那么,拒绝更改的最佳方法是什么?而且,我们如何知道上下文是否正在做某件事(IsBusy)?
我正在使用RIA服务,其中ObjectContext具有RejectChanges()方法。但是,我现在正在使用EF 4.4在桌面应用程序中,并且找不到该方法。所以,我的问题是:在允许用户对collection进行批量CrUD操作的场景中,我将如何恢复所有更改?我可以重新创建上下文并再次获取数据,但如果我需要将更改还原回1-2个实体,则这听起来非常不必要。DbContext和RejectChanges
那么,拒绝更改的最佳方法是什么?而且,我们如何知道上下文是否正在做某件事(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() {
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);
}
}
}
这个=的DbContext在这种情况下
删除的实体呢?另外,如何为其他用户更改的实体获取新数据,而不是您? – Goran
我知道这是一个老问题。但是,没有一个答案符合我的情况。我需要拒绝集合中只有一个实体的更改。这是对我工作:
var objectContext = (myDbContext as IObjectContextAdapter).ObjectContext;
objectContext.Refresh(RefreshMode.StoreWins, partMaster);
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;
}
}
}
}
这可能是一个古老的答案,但有用的任何新的访问者.... 的刷新功能将重新载入数据源对象并覆盖现有的变化新加载的实体的状态将保持不变。
public static void UndoEntityChanges(object Entity)
{
<EFModelContainer>.Entry(Entity).Reload();
}
重新创建上下文将是一个很好的解决方案。但是,我在同步相关数据时遇到了问题。一个例子是,我在ViewA上的CollectionA上有CRUD,在ViewB上有在COllectionB上的CRUD。 CollectionB还拥有对CollectionA的引用。因此,如果我有2个Context对象(既适用于CollectionA也适用于CollectionB),如果我更改ViewA的CollectionA,如何同步ViewB?当有一个上下文时,所有内容都是同步的,因为我们实际上只处理一个实例collectionA,而不是两个。重新创建“全局”上下文会造成混乱。 :)我使用“全局”上下文犯了错误吗? – Goran
至于“忙”,我担心如果我发出一个异步加载负载会发生什么,然后我尝试发出另一个负载,而以前没有完成?这样我可以检查它是否“忙碌”,这样我可以排队一个新的Load。 – Goran
+1注意到大多数人似乎错过了什么。关系:可以通过查看State!= Unchanged的Entries集合来追踪那些不会被拾取的变化。 (EF v6。) – mwardm