单个 MVC5 编辑页上的父/子 CRUD 操作

本文关键字:CRUD 操作 MVC5 编辑 单个 | 更新日期: 2023-09-27 18:34:35

我有一个使用 EF6 代码优先的 MVC 5 项目。它包括包含复杂子对象列表的模型。我需要能够在父对象的编辑页面上添加、更新和删除子对象,同时保存对父对象的更改。

我在如何在控制器中处理这些操作方面遇到了两难境地。这是相关代码。

模型:

public class Parent
{
    public int Id {get;set;}
    //other properties
    public virtual IList<Child> Children {get;set;}
}
public class Child
{
    public int Id {get;set;}
    //other properties
    public int Parent_Id {get;set;}
    [ForeignKey("Parent_Id")]
    public virtual Parent Parent {get;set;}
    [NotMapped]
    public bool toBeDeleted {get;set;}
}

控制器:

[HttpPost]
public ActionResult Edit([Bind(Include = "Id, Children")] Parent p)
{
    ...
    //For some reason children are brought in with Parent_Id = null.
    //Manually resetting it fixes this issue.
    //Needs to be set before parent = modified for referential integrity
    foreach(var c in p.Children)
    {
        c.Parent_Id = p.Id;
    }
    context.Entry(p).State = EntityState.Modified;
    for(int i = 0; i < p.Children.Count; i++)
    {
        if(p.c[i].toBeDeleted)
        {
            Child childToDelete = context.Children.Find(p.c[i].Id);
            context.Entry(childToDelete).State = EntityState.Deleted;
            i--;
        }
        else
        {
            context.Entry(p.c[i]).State = p.c[i].Id > 0 ? EntityState.Modified : EntityState.Added;
        }
    }
    context.SaveChanges();
    ...
}

我必须在删除后包含"i--",因为父对象已经设置为已修改,任何标记为删除的子对象都会立即从抛出循环的列表中删除。 (我最初有一个 foreach 循环,但当集合大小在循环中间发生变化时,这个问题会导致错误(

虽然我所拥有的有效,但感觉有点像拼凑的修复。在我看来,应该有一种更好的方法来实现这一点,而不是在每次删除后手动减少 for 循环中的迭代器以保持项目正确排列。有没有更好的方法可以做到这一点?有没有办法分别设置每个对象的实体状态,而不会影响相关对象的状态?

单个 MVC5 编辑页上的父/子 CRUD 操作

怎么样:

p.Children.Where(m => m.toBeDeleted).ToList().ForEach(m => p.Children.Remove(m));

只需从集合中删除子项,实体框架就会将其标记为删除。

此外,对于您的添加条件,如果您为Parent_Id添加了隐藏字段(如果没有,您应该这样做(,那么子项将设置其Parent_Id,除非他们是新字段。如果它们是新的,那么仅仅由于在ParentChildren集合中,它们将被添加,并且Parent_Id属性将由实体框架自动设置。最有可能的是,您的问题是尝试保存现有子项,这些子项Parent_Id属性因未发布而已清空。这将导致完整性错误,因为它在实体框架看来好像您希望Parent_Id更改为 null。