使用Entity Framework 7.0.0-rc1 / EntityFrameworkCore 1.0.0对子实体进行差异保存

时间:2016-07-05 15:47:38

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

我有一个基于ASP.Net MVC 6 / ASP.Net Core 1.0的应用程序,它通过Web API公开CRUD方法。

我正在使用Entity Framework 7.0.0-rc1,我计划将所有内容迁移到EF Core 1.0 / ASP.Net Core 1.0但尚未完成此操作。

这是一个模型类型的片段,它引起了我的设计问题:

public class ParentEntity
{
    public int Id { get; set; }
    public virtual ICollection<ChildEntity> ChildCollection { get; set; } = new ChildCollection();
}

public class Child
{
    public int Id { get; set; }
    public virtual ParentEntity ParentEntity { get; set; }
    public int? ParentEntityId { get; set; }
}

在我的ApplicationContext类中正确确保了所有关系,并且所有CRUD操作都按预期工作,包括保存ParentEntity时子实体的添加和更新。

例如,这是我通过API公开的Save方法:

// On some web API Save method :
[HttpPost]
public JsonResult Save(ParentEntity entity)
{
    if (entity.Id > 0) _context.Update(entity);
    else _context.Add(entity);
    var result = _context.SaveChanges();
    return Json(result);
}

传递给save方法的实体来自我的AngularJS后端。只要添加或修改了子实体,一切都按预期工作。

现在让我们想象后端收到一个ParentEntity加载了两个名为ChildEntityA的{​​{1}}。

现在在后端我删除B子实体并将其发布到save方法。

后端会保存所收到数据的更改:所有更新都会保留在BParentEntity A上。

但是B ChildEntity仍然存在于数据存储区中,这似乎是合乎逻辑的,因为没有迹象表明如何处理它。

所以我的问题是,因为在我看来这是一个非常常见的情况:我该如何处理?

我想象存储子集合的某个地方,保存更改,重新加载根实体,比较集合,确定应删除哪些,然后将其删除,但对我来说似乎相当困难和肮脏。还有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

你的问题的答案就在这里

https://msdn.microsoft.com/da-dk/magazine/mt694083

答案 1 :(得分:0)

根据上面MSDN博客文章中解释的一些提示,我已经通过它的基类在每个实体上实现了一个客户端状态字段:

public enum ObjectState
{
    Unchanged = 0,
    Added = 1,
    Modified = 2,
    Deleted = 3
}

public interface IObjectWithState
{
    ObjectState ClientState { get; set; }
}

public abstract class BaseEntity : IBaseEntity, IPrimaryKey
{
    public int Id { get; set; }
    public string Name { get; set; }

    [NotMapped]
    public bool IsNew => Id <= 0;
    [NotMapped]
    public ObjectState ClientState { get; set; } = ObjectState.Unchanged;
}

每当从客户端的集合中删除子实体时,我会将其保留在集合上,并将其标记为已删除。

然后我只需要在服务器端处理它:

_context.ChildEntityCollection.RemoveRange(
    entity.ChildCollection.Where(c => c.ClientState == ObjectState.Deleted).ToList()
);
_context.SaveChanges();

我在每个实体上实现了整个枚举,但是目前我只使用Deleted值,并且只通过关系。到目前为止,不需要其他值或根实体上的任何值。