【问题标题】:Does Entity Framework Core have a simple way of preventing the update of child or parent entities?Entity Framework Core 是否有防止子实体或父实体更新的简单方法?
【发布时间】:2020-04-22 13:51:03
【问题描述】:

我正在尝试编写一个 UpdateStatus 方法,它只会在我将更改保存到数据库时更新实体的状态字段。如果实体中的任何其他字段已更改,我不想将这些更改保存到数据库中。这对于实体自己的字段来说已经足够简单了,使用:

using (var context = new DataAccessContext())
{
    context.Attach(entity);
    context.Entry(entity).Property(e => e.StatusCode).IsModified = true;
    context.SaveChanges();
}

但是,我发现如果该相关实体没有设置键值,则任何可通过我正在设置其状态的实体的导航属性访问的相关实体都将被插入。因此,如果某个调用代码向entity.Children 添加了一个新的 Child 实体,并且 Child 实体的 ChildId 属性为 0,则该 Child 将被插入到数据库中。

在 EF Core 中是否有任何简单的方法可以避免插入相关实体?

我发现了一篇旧的 StackOverflow 帖子,它展示了如何在 pre-Core Entity Framework 中执行此操作:How do I stop Entity Framework from trying to save/insert child objects? 但是,该答案涉及遍历每个相关实体。 EF Core 中是否有更简单的方法?

我正在寻找一种更简单的方法的原因是我的实体层次结构有 5 层深。而且我发现仅分离实体的直接子级是不够的。您必须使用嵌套循环来分离孙子、曾孙等。如果您只分离直接的孩子,他们不会被插入,但 EF Core 会尝试插入新的孙子,并且会崩溃和烧毁,因为它没有插入他们的父母。它变得非常混乱。

我可以在更新其状态之前从数据库中读取实体的新副本,但我试图避免在写入之前必须进行读取。

【问题讨论】:

  • 你可以尝试清空相关数据而不是分离它。
  • @Dennis1679:谢谢。那成功了。如果你愿意这样回答,我会接受。
  • 很高兴我能帮上忙!我会回答的。

标签: entity-framework entity-framework-core


【解决方案1】:

您的问题在 EF Core 中非常简单。如果您不希望 EF Core 更改跟踪器操作处理相关数据,请设置 EntityEntry.State 而不是调用 DbContext / DbSet 等方法,例如 AttachAddUpdateRemove 等.

此行为与 EF6 不同,EF6 中的方法和设置状态是相同的,并且在 Saving Related Data - Adding a graph of new entities 文档主题中部分提及:

提示

使用EntityEntry.State 属性设置单个实体的状态。例如,context.Entry(blog).State = EntityState.Modified

所以在您的示例中,只需替换

context.Attach(entity);

context.Entry(entity).State = EntityState.Unchanged;

【讨论】:

    【解决方案2】:

    Entity Framework Core 会忽略关系,除非您明确表示 将它们包含在查询中。

    将实体附加到具有相关数据/子属性的数据库时,这些实体将包含在查询中。

    因此,要解决此问题,您只需将这些子属性设置为 null,然后 EF Core 将在您更新父对象时忽略子对象。

    【讨论】:

    • 添加更多信息:我设置了entity.Children = null;,即取消了子集合,而不是每个单独的子实体。我还发现我需要在致电context.Attach(entity); 之前执行此操作。如果我先调用 context.Attach 然后将子集合清空,任何新的子集合仍会插入到数据库中。
    • 我认为在 Ivan 的回答中设置状态比清空导航属性要安全得多。如果您不确切知道自己在做什么,这可能会导致持续的断绝关系。设置状态准确且安全。
    • 我同意。我不介意@SimonTewsi 是否会让 Ivan 的答案成为基于此的公认答案。
    • 我现在已将接受的答案更改为 Ivan 的答案。
    猜你喜欢
    • 2020-02-06
    • 1970-01-01
    • 2023-03-29
    • 2017-05-05
    • 1970-01-01
    • 2018-12-10
    • 1970-01-01
    • 2020-10-13
    • 2011-12-19
    相关资源
    最近更新 更多