在EF中更新父实体时如何添加/更新子实体 [英] How to add/update child entities when updating a parent entity in 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?
}
目前我有两个想法:
-
通过
model.Id获取名为
,并将的跟踪父实体
model.Id模型
中的值逐个分配给实体。这听起来很愚蠢在model.Children
我不知道哪个孩子是新的,哪个孩子被修改(甚至删除)。
Get a tracked parent entity named
existing
bymodel.Id
, and assign values inmodel
one by one to the entity. This sounds stupid. And inmodel.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屋!