不能为类型'MyTable'的实体调用成员'CurrentValues',因为该实体不存在于上下文中

不能为类型'MyTable'的实体调用成员'CurrentValues',因为该实体不存在于上下文中

问题描述:

我有一个使用Entity Framework v6.0的MVC应用程序。无论何时对DbContext进行更改,我都会覆盖SaveChanges()方法并在审核日志中记录这些修改。下面是审计日志记录过程的一部分代码:不能为类型'MyTable'的实体调用成员'CurrentValues',因为该实体不存在于上下文中

public override int SaveChanges() 
{ 
    var ChangesEntities = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted 
     || e.State == EntityState.Modified 
     || e.State == EntityState.Added).ToList(); 

    foreach (DbEntityEntry entry in ChangesEntities) 
    { 
     if (entry.State == EntityState.Modified) 
     { 
      SetCorrectOriginalValues(entry); 
     } 

     ... 
    } 

    ... 

    return base.SaveChanges(); 
} 

void SetCorrectOriginalValues(DbEntityEntry Modified) 
{ 
    var values = Modified.CurrentValues.Clone(); 
    Modified.Reload(); 
    Modified.CurrentValues.SetValues(values); 
    Modified.State = EntityState.Modified; 
} 

此代码然而通常工作,当我尝试做一个特定的更新,我收到以下错误:

异常消息:

Member 'CurrentValues' cannot be called for the entity of type 'MyTable' because the 
entity does not exist in the context. 
To add an entity to the context call the Add or Attach method of DbSet. 

异常堆栈跟踪:

at System.Data.Entity.Internal.InternalEntityEntry.get_CurrentValues() 
at System.Data.Entity.Infrastructure.DbEntityEntry.get_CurrentValues() 
at MyDatabaseName.DataLibrary.MyDatabaseEntities 
    .SetCorrectOriginalValues(DbEntityEntry Modified) 
at MyDatabaseName.DataLibrary.MyDatabaseEntities.SaveChanges() 
... 

异常消息是什么意思?何时以及为什么CurrentValues无法被调用?这是什么意思,该实体不存在于上下文中?

在MyDatabaseEntities.Context.cs,延伸DbContext, 'MyTable的' 似乎存在:

public virtual DbSet<MyTable> MyTables { get; set; } 

我查了实体框架模型图,和 'MyTable的' 存在那里。

+0

你确定currentvalues不包含soemthing添加到上下文,但没有保存到db – Steve

+0

@Steve你是什么意思?我不太熟悉这些实体框架功能,所以我可能会错过简单的东西。审计日志记录总是在'base.SaveChanges()'被调用之前发生,并且这似乎永远不成问题。这是你指的是什么? –

+0

你试过附加你的dbSet吗? –

感谢上面评论中给出的指针,我能够找到错误源自的位置,并找出触发错误的原因。基本的答案是这是由并发问题引起的。我正尝试更新之前调用中已被删除的MyTable对象。

在我的网页,我有MyTable对象的表:

ID | Name | Delete Button 
---- | ---- | ------------- 
1 | abc | button1 
2 | xyz | button2 

每一行都有一个删除按钮。单击按钮时,会发生以下操作:

  1. 传入要删除的对象的ID
  2. 获取HTML表格中显示的MyTable对象的列表,不包括ID设置为要删除的对象。
  3. 循环遍历所有对象并保存所有修改,例如对Name字段的更改。
  4. DbSet中删除对象,该对象的ID对应于单击的按钮。

在第一组操作完成之前单击第二个删除按钮时出现问题。这种情况发生时,有2组不同的行动同时运行,而事件的顺序看起来是这样的:

动作1:单击Button(ID删除= 1)
动作1:获取MyTable的要更新的对象的列表(包括ID 2)
操作2:点击按钮2(ID删除= 2)
操作2:获取MyTable的对象的列表来更新(仍然包括ID 1)
行动1 :更新所有MyTable的对象(ID 2)
动作1:删除ID 1
行动2:更新所有MyTable的对象 - 错误因为ID 1已被删除!

我最终通过重新排列某些事件的顺序并添加一个检查来确保对象在DbSet而不仅仅是HTML表中存在,然后尝试更新它。