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

时间:2014-12-18 18:36:07

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

我有一个使用EF6 Code First的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循环中的迭代器,以保持项目正确排列。有一个更好的方法吗?有没有办法分别设置每个对象的实体状态而不影响相关对象的状态?

1 个答案:

答案 0 :(得分:1)

怎么样:

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

只需从集合中删除子项,Entity Framework就会将它们标记为删除。

此外,对于您的添加条件,如果您为Parent_Id添加了一个隐藏字段(如果没有,则应该添加),那么孩子们将设置Parent_Id,除非他们'重新开始。如果它们是新的,那么仅仅因为Children Parent的{​​{1}}集合,它们将被添加,并且实体框架将自动设置Parent_Id属性。最有可能的是,您的问题在于尝试保存已存在Parent_Id属性的现有子项,因为它未发布。这将导致完整性错误,因为它查看实体框架,就好像您想要Parent_Id更改为null。