这两个实体是一对多的关系(由代码第一流畅的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控制器中,我有动作创建父实体(工作正常)并更新父实体(有一些问题) . 更新操作如下所示:
public void Update(UpdateParentModel model)
{
//what should be done here?
}
目前我有两个想法:
-
通过
model.Id
获取名为existing
的被跟踪父实体,并将model
中的值逐个分配给实体 . 这听起来很愚蠢 . 在model.Children
我不知道哪个孩子是新的,哪个孩子被修改(甚至删除) . -
通过
model
创建一个新的父实体,并将其附加到DbContext并保存 . 但是DbContext如何知道子进程的状态(new add / delete / modified)?
实现此功能的正确方法是什么?
7 回答
在这种情况下,尝试使用LINQ支持的ForEach循环:
因为发布到WebApi控制器的模型与任何实体框架(EF)上下文分离,所以唯一的选择是从数据库加载对象图(父项包括其子项)并比较已添加,删除或更新 . (除非您在分离状态期间(在浏览器中或在任何地方)使用您自己的跟踪机制跟踪更改,我认为这些更改比以下更复杂 . )它可能如下所示:
...CurrentValues.SetValues
可以根据属性名称将任何对象和属性值映射到附加实体 . 如果模型中的属性名称与实体中的名称不同,则无法使用此方法,并且必须逐个分配值 .我一直在搞这样的事......
您可以使用以下内容调用:
不幸的是,如果子类型上还有需要更新的集合属性,这种情况就会失败 . 考虑尝试通过传递IRepository(使用基本的CRUD方法)来解决这个问题,该IRepository将负责自己调用UpdateChildCollection . 将调用repo而不是直接调用DbContext.Entry .
不知道这将如何大规模执行,但不知道还有什么可以解决这个问题 .
如果您正在使用EntityFrameworkCore,则可以在控制器后期操作中执行以下操作(Attach method递归附加导航属性,包括集合):
假设已更新的每个实体具有在来自客户端的发布数据中设置和提供的所有属性(例如,将不用于实体的部分更新) .
您还需要确保为此操作使用新的/专用实体框架数据库上下文 .
有一些项目可以使客户端和服务器之间的交互更容易,只要它涉及保存整个对象图 .
这里有两个你想看的:
Trackable Entities
Breeze#
上述两个项目都会在断开的实体返回服务器时识别它们,检测并保存更改,并返回受客户端影响的数据 .
只是 proof of concept
Controler.UpdateModel
将无法正常工作 .全班here:
好,朋友们 . 我曾经有过这个答案,但一路上就丢了 . 当你知道有更好的方法却无法记住是否找到它时,绝对折磨!这很简单 . 我刚试过多种方式 .
您可以用新的列表替换整个列表! SQL代码将根据需要删除和添加实体 . 无需关心自己 . 一定要包括儿童收集或没有骰子 . 祝好运!