实体框架 - 使用添加/修改的子实体和孙实体更新实体

时间:2015-06-24 04:41:56

标签: c# .net entity-framework asp.net-web-api entity-framework-6

我不确定我是否以正确的方式这样做,所以需要建议。

我有一个实体,这个实体有一个子集合,每个子实体都有另一个子集合。像这样的东西(简化例子)

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添加新的MyGrandChildMyEntity对象,或者更新MyChildMyGrandChild对象,则更改不会提交给数据库?我将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并相应地设置其状态?

1 个答案:

答案 0 :(得分:1)

是的,你必须这样做。

当您在DbContext范围内完成所有工作时,需要注意跟踪实体中发生的变化,并且您必须不做任何让DbContext知道更改的内容。

但是,在多层应用程序中,当您在层之间移动实体时,它们不能保留在DbContext范围内,因此您负责跟踪cahnges。

Julie Lerman建议实施一个界面来跟踪每个实体的状态。此接口具有保持实体状态的属性。这在客户端修改并在服务器上访问以设置每个实体状态:获取服务器端的实体,将它们附加到上下文,并根据跟踪接口属性修改其状态。 (我找不到参考文献,但是她的编程实体框架书和她的Pluralsight课程中都有它。)

Trackable Entities也可能符合您的利益。

如果您希望“自动”发生这种情况,您可以使用Breeze。这使您可以使用JavaScript代码在客户端轻松公开EF模型。此代码能够在客户端跟踪更改(并执行许多其他操作,如验证),并将它们发送回服务器以更新数据库。入门很容易。基本上你需要为服务器安装NuGet包来实现一个Breeze控制器,这个控制器只用很少的代码行完成,而实现JavaScript代码的客户端的NuGet包也是如此。建议使用一些MVVM JavaScript库,如KnockoutAngularJS,因为订阅由这些库创建的可观察项会自动跟踪更改。

相关问题