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

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

问题描述

这两个实体是一对多关系(由代码第一流利api构建)。

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获取名为的跟踪父实体 model.Id ,并将模型中的值逐个分配给实体。这听起来很愚蠢在 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).

通过 model 创建一个新的父实体,并将其附加到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 entity-framework (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 wherever) 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 from the names in the entity you can't use this method and must assign the values one by one.

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

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