如何更新在EF父实体时添加/更新子实体 [英] How to add/update child entities when updating a parent entity in EF

查看:120
本文介绍了如何更新在EF父实体时添加/更新子实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这两个实体是一个一对多的关系。

The two entities are one-to-many relationship (built by code first fluent api).

public class Parent
{
    public Parent()
    {
        this.Children = new List<Child>();
    }

    public int Id { get; set; }

    public virtual ICollection<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }

    public int ParentId { get; set; }

    public string Data { get; set; }
}

在我的WebAPI控制器我有行动,以创建一个父实体(这是工作的罚款),并更新父实体(其中有一些问题)。更新操作是这样的:

In my WebApi controller I have actions to create a parent entity(which is working fine) and update a parent entity(which has some problem). The update action looks like:

public void Update(UpdateParentModel model)
{
    //what should be done here?
}

目前我有两个想法:


  1. 获取现有 model.Id 名为跟踪父实体,并在<$赋值C $ C>模式逐一的实体。这听起来很愚蠢。而在 model.Children 我不知道这孩子是新的,这孩子被修改(甚至删除)。

  1. Get a tracked parent entity named existing by model.Id, and assign values in model one by one to the entity. This sounds stupid. And in model.Children I don't know which child is new, which child is modified(or even deleted).

通过创建模式一个新的母公司,它连接到的DbContext并保存。但是的DbContext怎么能知道孩子的状态(新添加/删除/修改)?

Create a new parent entity via model, and attached it to the DbContext and save it. But how can the DbContext know the state of children (new add/delete/modified)?

什么是实现此功能的正确方法是什么?

What's the correct way of implement this feature?

推荐答案

由于该被发布到的WebAPI控制器模型从任何EF背景下唯一的选择就是装载对象图分离(母公司包括其子女)从数据库和比较了儿童已被添加,删除或更新。 (除非你想跟踪用自己的跟踪机制分离状态时(的变化在浏览器或徘徊无论),这在我看来是比下面更复杂)可能是这样的:

Because the model that gets posted to the WebApi controller is detached from any EF context the only option is to load the object graph (parent including its children) from the database and compare which children have been added, deleted or updated. (Unless you would track the changes with your own tracking mechanism during the detached state (in the browser or whereever) which in my opinion is more complex than the following.) It could look like this:

public void Update(UpdateParentModel model)
{
    var existingParent = _dbContext.Parents
        .Where(p => p.Id == model.Id)
        .Include(p => p.Children)
        .SingleOrDefault();

    if (existingParent != null)
    {
        // Update parent
        _dbContext.Entry(existingParent).CurrentValues.SetValues(model);

        // Delete children
        foreach (var existingChild in existingParent.Children.ToList())
        {
            if (!model.Children.Any(c => c.Id == existingChild.Id))
                _dbContext.Children.Remove(existingChild);
        }

        // Update and Insert children
        foreach (var childModel in model.Children)
        {
            var existingChild = existingParent.Children
                .Where(c => c.Id == childModel.Id)
                .SingleOrDefault();

            if (existingChild != null)
                // Update child
                _dbContext.Entry(existingChild).CurrentValues.SetValues(childModel);
            else
            {
                // Insert child
                var newChild = new Child
                {
                    Data = childModel.Data,
                    //...
                };
                existingParent.Children.Add(newChild);
            }
        }

        _dbContext.SaveChanges();
    }
}

... CurrentValues​​.SetValues​​ 可以采取任何对象和属性值映射到基于属性名附加实体。如果模型中的属性名是在实体则不能使用这种方法,必须由一个指定值一个名称不同。

...CurrentValues.SetValues can take any object and maps property values to the attached entity based on the property name. If the property names in your model are different to the names in the entity you can't use this method and must assign the values one by one.

这篇关于如何更新在EF父实体时添加/更新子实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆