5

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

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

我用它在重新计算之前清除表格。下面我列出了我的方法的简化版本。请注意,表的键是一个字符串(即不是标识键),因此我将使用与 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()
}

这第一次运行良好,但如果我再次运行它,我会在 SaveChanges() 命令上出现异常,该命令由 uow.Commit() 调用。例外是:

Message="调用的目标已抛出异常。"

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

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

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

提前致谢。

4

2 回答 2

5

在我遇到 Julia Lerman 的优秀书籍'Programming Entity Framework: DbContext'之前,我还没有找到关于在实体框架中安全使用 ExecuteSqlCommand 的问题的好的答案。

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

    yourDbContext.Entry(TheTrackedEntityYouWantToUpdate).Reload();

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

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

于 2013-02-16T11:23:47.630 回答
0

您是否使用身份作为密钥?是不是 ObjectContext 正在跟踪您从数据库中删除的旧实体并正在添加新实体。新实体(如果您的密钥没有标识列)被赋予与旧实体相同的密钥。由于上下文已经在跟踪旧实体,因此它会获得一个带有被跟踪实体键的新实体。EF 假定所有更改都是通过对象上下文完成的,而不是来自数据库。如果您删除这样的实体,您可能应该丢弃上下文

于 2012-10-24T16:06:37.273 回答