5

我们首先使用实体​​框架代码,当我们不想回滚插入、更新和删除的实体更改时,我遇到了问题SaveChanges()

具体来说,我有一个用作 TableEditor 的 datagridview 来更改一些辅助表。datagridview 绑定到DbSet<TEntity>.

我的更新回滚似乎工作正常,我只是将 currentValues 设置回它们的 OriginalValues,并将状态更改为unchanged.

当一条记录插入到gridview(但没有保存更改)时,它永远不会出现在实体类中,我再也看不到它了......所以我猜它不会进入dbSet,并且没有回滚需要这个吗?

但我的主要问题在于 Delete

据我了解,当一条记录被“删除”(例如tableData.Remove(currentItem);)时,它只是被标记为删除,直到调用 SaveChanges 为止。因此,如果我将 State 从deletedback 更改为unchanged,那应该可以处理回滚,对吗?

好吧,记录确实再次显示,但记录的导航属性消失了!(即包含外键和与其他实体的必需关系的列)。为什么是这样??!

这是我到目前为止所拥有的:

    public void RollbackChanges(DbEntityEntry entry)
    {
        if (entry.State == EntityState.Modified)
        {
            foreach (var propertyName in entry.OriginalValues.PropertyNames)
            {
                entry.CurrentValues[propertyName] = entry.OriginalValues[propertyName];
            }
            entry.State = EntityState.Unchanged;
        }
        else if (entry.State == EntityState.Deleted)
        {
            entry.State = EntityState.Unchanged;
        }
        else if ((entry.State == EntityState.Added) || (entry.State == EntityState.Detached))
        {
            MessageBox.Show("I don't think this ever happens?");
        }
    }

示例用法:

    foreach (var entity in db.CertificationDecisions)
                {
                    DbEntityEntry entry = db.Entry(entity );
                    if (entry.State != EntityState.Unchanged)
                    {
                        RollbackChanges(entry);
                    }
                }

任何想法为什么导航属性会从记录中消失?(或者我能做些什么让他们回来?)


编辑: @Chris 关于使用Refresh

我正在使用DbContext,所以我用这一行替换了我的回滚方法:

((IObjectContextAdapter)db).ObjectContext.Refresh(RefreshMode.StoreWins, db.CertificationDecisions);

但是,这似乎并没有重新加载上下文,因为记录仍然丢失......我用Refresh错了吗?

这听起来像是我的问题的可能解决方案,但我仍然想知道为什么会删除导航属性?

4

2 回答 2

3

任何想法为什么导航属性会从记录中消失?

由于外键关系,导航属性很可能被删除。让我们参加以下课程:

public class Dog
{
  public guid ID { get; set; }
  public string Title { get; set; }
}

public class Person
{
  public guid ID { get; set; }

  public ICollection<Dog> FavoriteDogs { get; set; }
}

在数据库中,FavoriteDogs 的集合是一个表,该表同时引用了 Person 和 Dog,但被导航属性自动隐藏。当状态设置为已删除时,EF 会自动将参考实体标记为已删除。如果父实体设置为未更改,实体框架不会将这些引用实体设置为未更改,因为这样做不需要引用完整性(仅适用于删除操作)。

或者我能做些什么让他们回来?

目前 EF 中没有可以执行此操作的自动化流程。 我不相信甚至有手动更改引用实体的方法。并且新的Entity Framework 5 没有公开任何查看或更改DbRefrenceEntry.

也许试试 DbReferenceEntry。重新加载

于 2012-12-19T18:42:28.893 回答
2

这并不是我的问题的真正答案,而是到目前为止似乎对我有用的替代方案(以防有人正在寻找这个问题的答案):

基本上,我创建了一个新上下文并将一个实体从新上下文传递到我的表单。如果我取消表单,我只需处理上下文,因此不会保存任何更改(无需回滚)。如果我保存表单,那么我会保存新上下文中的更改,但是我需要让我的原始上下文知道这些更改。

所以我使用.Refresh,它似乎成功地找到了新实体,但不会删除已删除的实体。然后我遍历实体并将它们与数据库值进行比较。

如果数据库返回“null”,我们就知道该实体已在数据库中删除,需要从上下文中删除。(但是,我无法在循环中将其删除,因为在枚举时尝试更改上下文的内容会导致错误,因此我将条目添加到列表中,然后在单独的循环中从上下文中删除.)

下面是代码:(
注意:我不保证这是一个好的解决方案,但它似乎对我有用)

            using (FmlaManagementContext auxDb = new FmlaManagementContext())
            {
                AuxiliaryTableEditor<State> statesTableEditor = new AuxiliaryTableEditor<State>(auxDb.States);
                if (statesTableEditor.ShowDialog() != DialogResult.OK)
                {
                    auxDb.Dispose();
                }
                else
                {
                    auxDb.SaveChanges();
                    auxDb.Dispose();

                    //refresh to pick up any new
                    ((IObjectContextAdapter)db).ObjectContext.Refresh(RefreshMode.StoreWins, db.States);

                    //loop through to remove deleted
                    List<State> nulls = new List<State>();
                    foreach (State state in db.States.Local)
                    {
                        DbEntityEntry entry = db.Entry(state);
                        DbPropertyValues databaseValues = entry.GetDatabaseValues();
                        if (databaseValues == null)
                        {
                            nulls.Add(state); 
                        }
                    }
                    foreach (State state in nulls)
                    {
                        db.States.Remove(state);
                    }
                }
            }

如果我最终改变这个或发现它的问题,我会尽量记住回来更新......

于 2012-12-21T21:31:29.503 回答