创建:IEntityChangeTracker的多个实例无法引用实体对象

时间:2017-03-03 07:55:31

标签: c# asp.net asp.net-mvc entity-framework dbcontext

我创建了一个页面 asp.net MVC ,用于将记录插入数据库,我在这里提供了一个预览按钮,以便在保存之前查看数据在客户端的外观。我正在使用session将模型传递给预览页面。在预览页面上,我创建了一个按钮,它将会话中的模型保存到数据库,但它会抛出异常" IEntityChangeTracker" 的多个实例无法引用实体对象。 我使用相同的dbContext。我曾尝试过很多用户提供的解决方案,但他们并不适合我。我附上了引发异常的部分代码。请看我在哪里做错了。

以下是我保存记录的代码

var model = Session[Constants.SessionVariables.ProjectModelForPreview] as Project;
if (create != null)
{
    if (model.Id == 0)
    {
        if (model.IsFeatured)
        {
            foreach (var item in dbContext.Projects.Where(p => p.IsFeatured == true))
            {
                item.IsFeatured = false;
            }
            dbContext.SaveChanges();
        }

        dbContext.Entry(model).State = EntityState.Unchanged;
        dbContext.SaveChanges();
        TempData["SuccessMessage"] = "Project created successfully.";
        return RedirectToAction("Index");
    }
}

2 个答案:

答案 0 :(得分:1)

您的控制器以及您的DbContext将根据请求进行实例化。因此,您的应用程序遵循以下流程:

  • 请求1实例化DbContext 1.
  • 您通过DbContext加载实体1.正在跟踪此实体,实体本身拥有对DbContext 1的引用。
  • 您将此实体存储在会话中,使旧的DbContext保持活动状态。这是有效的,因为默认会话状态适用于InProc,而不是序列化。
  • 请求2进来,DbContext 2被实例化。
  • 从会话中检索实体。
  • 您尝试通过DbContext 2保存仍然被DbContext 1跟踪的实体。这会抛出。

现在解决方案有各种方法:

  • 根本不要在会话中保存实体。坚持下去,并在连续的请求中再次查看它们。
  • 通过手动序列化来保存会话中的实体。
  • 使用.AsNoTracking()加载实体。

答案 1 :(得分:1)

让我们暂时忽略原来的问题,一旦你重构代码就会解决它

1)如果由于某种原因您在请求中使用相同的上下文,请停止。   (我不认为你这样做)。

2)不要在会话中保存被跟踪的实体*   在谷歌上搜索以查看EF如何跟踪更改。

3)再次阅读1和2

*使用.AsNoTracking()或在新模型中投影您的实体并将其保存在会话中