创建:一个实体对象不能被IEntityChangeTracker的多个实例引用
问题描述:
我已经创建了一个页面asp.net MVC用于插入记录到数据库,我在这里给出一个预览按钮来查看数据如何在客户端看起来之前保存它。我正在使用会话将模型传递到预览页面。在预览页面上,我创建了一个按钮,可以将模型保存到数据库的会话中,但会抛出异常“IEntityChangeTracker的多个实例不能引用实体对象”。 我正在使用相同的dbContext。我尝试了许多用户提供的解决方案,但他们不适合我。我附上了引发异常的代码部分。请看我做错了什么。创建:一个实体对象不能被IEntityChangeTracker的多个实例引用
这里就是我节省纪录
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");
}
}
答
你的控制器代码,因此你的DbContext,是每个请求实例化。所以,你的应用程序遵循这一流程:
- 请求1实例的DbContext 1.
- 您通过的DbContext 1中装入实体此实体被追踪,以及实体本身持有到的DbContext 1
- 参考您将此实体存储在会话中,保持旧的DbContext存活。这是有效的,因为默认的会话状态工作在InProc上,而不是通过序列化。
- 请求2进来,DbContext 2得到实例化。
- 实体从会话中检索。
- 您尝试通过DbContext 2保存实体,该实体仍由DbContext 1进行跟踪。这将引发。
现在的解决方案有多种方法:
- 在会话中不要保存实体的。坚持下去,并在连续的请求中再次查看它们。
- 通过手动序列化它们来保存会话中的实体。
- 使用
.AsNoTracking()
加载实体。
答
让我们忽略了原来的问题,现在,它将一旦你如果由于某种原因,你正在使用跨请求相同的上下文重构代码
1)解决了,停下来。 (我不认为你这样做)。
2)不要在会话中保存跟踪的实体* 在google上搜索以查看EF如何跟踪更改。
3)阅读1和2再次
*使用.AsNoTracking()或项目的实体在一个新的模型,并保存在会话
您没有使用相同的背景下...告诉我们更多code.how你在下一个请求中获得相同的上下文吗? –
我正在使用基础控制器,我已经声明了上下文 –
因此,第一次创建记录并将它保存在会话中时,第二次尝试将它附加到不同的上下文中,这就是为什么您可能会遇到错误。如果我不想错过任何你有更大的问题,请不要在会话中保存跟踪的实体 –