c# - 另一个相同类型的实体已经具有相同的主键值

标签 c# asp.net-mvc entity-framework asp.net-mvc-5

我正在为具有一对多关系的模型开发一种编辑方法: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);
            }
        }
    }

我的思考过程是这样的:

  1. 如果网格已添加到网格中,则将其添加到 Grid.Gridboxes 集合中。
  2. 如果网格框的位置或大小已更改,请更新数据库中的这些值(使用 db.Entry(originalGridbox).CurrentValues.SetValues(gridbox)
  3. 如果从网格中删除了一个网格框,则将其从 Grid.Gridboxes 集合中删除

所以我无法理解上面的错误。主键是 GridboxID。

观察:添加新的网格框和调整现有网格框的大小都没有问题。收到错误后,我可以返回网格,更改已保存。问题似乎与现有的网格框有关。由于某种原因,它会尝试将它们重新添加到数据库中。

最佳答案

反序列化 json 对象后,尝试在调用更新方法之前将其附加到当前的数据库上下文 - 这就是更新失败的原因,因为它有两个具有相同 ID 的对象。代码如下:

   db.grids.Attach(grid);

这样 ef 应该正确跟踪对象上的所有更改。

关于c# - 另一个相同类型的实体已经具有相同的主键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073978/

相关文章:

c# - Swagger 未加载 - 无法加载 API 定义 : Fetch error undefined

c# - sqlite, mono, C# 跨平台

c# - MVC5中如何设置默认路由

c# - 使用x :Name in MVVM动态添加控件

c# - 关于将 List<T> 打印到屏幕的问题

css - ASP .NET MVC 5 - 减少左边距

css - ASP.NET MVC Bootstrap iPhone 导航栏 UI 问题

c# - 如何在另一个项目中分离 Entity Framework

c# - 如何通过c#mvc函数传递两个参数来调用存储过程

c# - 使用 EF6+MVC5 渲染网页时性能不佳。为什么?