实体框架:由于ObjectStateManager,使用ExecuteSqlCommand清除表会导致异常

Jon*_*ith 5 entity-framework ef-code-first

我使用EF5 Code First,需要一种快速清理表格的方法.因此我制作了一个非常简单的方法来使用ExecuteSqlCommand来提供快速表清除.代码如下:

    public void FastClearTable(Type tableType)
    {
        Context.Database.ExecuteSqlCommand(
            string.Format("delete from {0}", PluraliseTableName(tableType.Name)));
    }
Run Code Online (Sandbox Code Playgroud)

我在重新计算之前使用它来清除表格.下面我列出了我的方法的简化版本.请注意,表的键是一个字符串(即不是标识键),因此我使用与ExecuteSqlCommand删除的条目相同的键放入新条目.

public int ComputeNewTableContent( IRepository<MyClass> rep, IUnitOfWork uow)
{
     if ( rep.GetUntracked().Count() > 0)
           uow.FastClearTable( typeof(MyClass));

     --- compute new entries and call rep.Insert( newEntry) for each one ---
     uow.Commit();    //This calls DbContext.SaveChanges()
}
Run Code Online (Sandbox Code Playgroud)

这在第一次工作正常,但如果我再次运行它,我会在SaveChanges()命令上得到一个异常,该命令由uow.Commit()调用.例外是:

Message ="调用目标抛出了异常."

InnerException Message ="对数据库的更改已成功提交,但更新对象上下文时发生错误.ObjectContext可能处于不一致状态.内部异常消息:AcceptChanges无法继续,因为对象的键值与另一个对象冲突ObjectStateManager.在调用AcceptChanges之前,确保键值是唯一的."

如果发现这个存档的MSDN 帖子,并且在底部该人有同样的问题,但没有答案.我的观点是数据的内存版本仍然存在,并且不知道ExecuteSqlCommand.但是我还不了解EF还知道如何解决它.

我当然可以通过使用"正常"删除来绕过它,但我希望有人解释发生了什么以及我如何处理它.这将提高我对实体框架的了解.

提前致谢.

Jon*_*ith 5

我没有找到关于在实体框架中安全使用ExecuteSqlCommand的问题的一个很好的答案,直到我遇到Julia Lerman的优秀书籍"Programming Entity Framework:DbContext".

她介绍了ExecuteSqlCommand的使用(第226页),但最重要的是,她提到在ExecuteSqlCommand之后使用Reload命令来更新本地(第138页).这会从数据库中更新内存中实体.您可以按如下方式使用它:

    yourDbContext.Entry(TheTrackedEntityYouWantToUpdate).Reload();
Run Code Online (Sandbox Code Playgroud)

这正是我所需要的.谢谢朱莉娅.

我认为Julia Lerman的DbContext书对于任何使用Code First规划实际应用程序的人来说都是必须的.