我不确定我是否以正确的方式这样做,所以需要建议。
我有一个实体,这个实体有一个子集合,每个子实体都有另一个子集合。像这样的东西(简化例子)
public MyEntity() {
public long Id { get; set; }
public ICollection<MyChild> Children { get; set; }
}
public MyChild() {
public long Id { get; set; }
public long MyEntityId { get; set; }
public MyEntity MyEntity { get; set; }
public ICollection<MyGrandChild> Children { get; set; }
}
public MyGrandChild() {
public long Id { get; set; }
public long MyChildId { get; set; }
public MyChild MyChild { get; set; }
public string Name { get; set; }
}
现在,在我们的应用程序中,用户从webApi中将此实体检索到angularJs应用程序中。然后,用户更新实体(和子实体)并将实体传递回webApi。我使用模型将对象从webApi传递给angularJs应用程序,它们看起来像这样。
public MyEntityModel() {
public long Id { get; set; }
public ICollection<MyChildModel> Children { get; set; }
}
public MyChildModel() {
public long Id { get; set; }
public ICollection<MyGrandChildModel> Children { get; set; }
}
public MyGrandChildModel() {
public long Id { get; set; }
public string Name { get; set; }
}
将模型传递回webApi后,我使用Auto Mapper将它们转换回实体对象。
现在有点困惑,我现在将对象传递给我的服务层,我的方法看起来与此类似
public Task<int> UpdateAsync(MyEntity updated) {
_context.Entry(updated).State = EntityState.Modified;
return _context.SaveChangesAsync();
}
如果我在MyEntity存在后向MyChild
添加新的MyGrandChild
或MyEntity
对象,或者更新MyChild
或MyGrandChild
对象,则更改不会提交给数据库?我将UpdateAsync
方法更改为此,但这真的需要吗?
public Task<int> UpdateAsync(MyEntity updated) {
_context.Entry(updated).State = EntityState.Modified;
foreach (var child in updated.Children) {
if (child.Id == 0) {
_context.Entry(child).State = EntityState.Added;
} else {
_context.Entry(child).State = EntityState.Modified;
}
foreach (var grand in child.Children) {
if (grand.Id == 0) {
_context.Entry(grand).State = EntityState.Added;
} else {
_context.Entry(grand).State = EntityState.Modified;
}
}
}
return _context.SaveChangesAsync();
}
我是否真的必须遍历每个集合和子集合,检查id是否等于0并相应地设置其状态?
答案 0 :(得分:1)
是的,你必须这样做。
当您在DbContext
范围内完成所有工作时,需要注意跟踪实体中发生的变化,并且您必须不做任何让DbContext知道更改的内容。
但是,在多层应用程序中,当您在层之间移动实体时,它们不能保留在DbContext
范围内,因此您负责跟踪cahnges。
Julie Lerman建议实施一个界面来跟踪每个实体的状态。此接口具有保持实体状态的属性。这在客户端修改并在服务器上访问以设置每个实体状态:获取服务器端的实体,将它们附加到上下文,并根据跟踪接口属性修改其状态。 (我找不到参考文献,但是她的编程实体框架书和她的Pluralsight课程中都有它。)
Trackable Entities也可能符合您的利益。
如果您希望“自动”发生这种情况,您可以使用Breeze。这使您可以使用JavaScript代码在客户端轻松公开EF模型。此代码能够在客户端跟踪更改(并执行许多其他操作,如验证),并将它们发送回服务器以更新数据库。入门很容易。基本上你需要为服务器安装NuGet包来实现一个Breeze控制器,这个控制器只用很少的代码行完成,而实现JavaScript代码的客户端的NuGet包也是如此。建议使用一些MVVM JavaScript库,如Knockout或AngularJS,因为订阅由这些库创建的可观察项会自动跟踪更改。