我正在为具有一对多关系的模型开发一种编辑方法:Grid 和 Gridboxes。每当我尝试编辑网格的内容时,我都会收到此错误:
Attaching an entity of type 'MyProject.Models.Gridbox' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
这是我的编辑方法:
[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);
}
}
}
我的思考过程是这样的:
- 如果网格已添加到网格中,则将其添加到 Grid.Gridboxes 集合中。
- 如果网格框的位置或大小已更改,请更新数据库中的这些值(使用
db.Entry(originalGridbox).CurrentValues.SetValues(gridbox)
。 - 如果从网格中删除了一个网格框,则将其从 Grid.Gridboxes 集合中删除
所以我无法理解上面的错误。主键是 GridboxID。
观察:添加新的网格框和调整现有网格框的大小都没有问题。收到错误后,我可以返回网格,更改已保存。问题似乎与现有的网格框有关。由于某种原因,它会尝试将它们重新添加到数据库中。
最佳答案
反序列化 json 对象后,尝试在调用更新方法之前将其附加到当前的数据库上下文 - 这就是更新失败的原因,因为它有两个具有相同 ID 的对象。代码如下:
db.grids.Attach(grid);
这样 ef 应该正确跟踪对象上的所有更改。
关于c# - 另一个相同类型的实体已经具有相同的主键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073978/