我正在为具有一对多关系的模型编写一个编辑方法:Grid和Gridboxes。每当我尝试编辑网格的内容时,我都会收到此错误:
附加类型' MyProject.Models.Gridbox'的实体。失败,因为同一类型的另一个实体已具有相同的主键值。使用'附加'方法或将实体的状态设置为“未更改”#39;或者'修改'如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,请使用'添加'方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者'修改'酌情。
这是我的编辑方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "GridID,Title")] Grid grid, string gridboxes)
{
GridboxCollection gridboxList = JsonConvert.DeserializeObject<GridboxCollection>(gridboxes);
grid.Gridboxes = gridboxList.Gridboxes;
UpdateGridGridboxes(gridboxList.Gridboxes, grid);
if (ModelState.IsValid)
{
db.Entry(grid).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(grid);
}
这是帮助UpdateGridGridboxes
方法:
private void UpdateGridGridboxes(Gridbox[] gridboxes, Grid gridToUpdate)
{
// If edited grid has no gridboxes (user has deleted all of them)
if (gridboxes.Length == 0)
{
gridToUpdate.Gridboxes = new List<Gridbox>();
return;
}
// If edited grid does have at least one gridbox
else
{
gridToUpdate.Gridboxes = gridToUpdate.Gridboxes.ToList();
foreach (var gridbox in gridboxes)
{
// If there is no gridboxID (if it's a new gridbox), add it to the grid's gridbox list
if (gridbox.GridBoxID == 0)
{
gridbox.GridID = gridToUpdate.GridID;
gridToUpdate.Gridboxes.Add(gridbox);
db.Entry(gridbox).State = EntityState.Added;
db.SaveChanges();
}
// If it's an existing gridbox, update its properties
else
{
var originalGridbox = db.Gridbox.Find(gridbox.GridBoxID);
if (originalGridbox != gridbox)
{
db.Entry(originalGridbox).CurrentValues.SetValues(gridbox);
db.Entry(originalGridbox).Property(x => x.GridID).IsModified = false;
db.Entry(originalGridbox).State = EntityState.Modified;
db.SaveChanges();
}
else
{
db.Entry(originalGridbox).State = EntityState.Unchanged;
}
}
}
}
var existingGridboxesInGrid = gridToUpdate.Gridboxes;
// iterate through existing gridboxes and remove the ones that have been deleted from the grid
foreach (var existingGridboxInGrid in existingGridboxesInGrid)
{
if (!gridboxes.Contains(existingGridboxInGrid))
{
gridToUpdate.Gridboxes.Remove(existingGridboxInGrid);
}
}
}
我的思维过程是这样的:
db.Entry(originalGridbox).CurrentValues.SetValues(gridbox)
。所以我无法理解上面的错误。主键是GridboxID。
观察:添加了新的网格框,并且调整了现有网格框的大小而没有任何问题。收到错误后,我可以回到网格并保存更改。问题似乎与现有的网格盒有关。它出于某种原因尝试将它们重新添加到数据库中。
答案 0 :(得分:0)
反序列化后,json对象尝试在调用update方法之前将其附加到当前的db上下文 - 这就是为什么它在更新时失败,因为它有两个具有相同ID的对象。这个代码就像这样:
db.grids.Attach(grid);
这样,ef应该正确跟踪对象上的所有更改。