【问题标题】:Using Entity Framework Core 5, how can I automatically updated related entities when calling SaveChanges()?使用 Entity Framework Core 5,如何在调用 SaveChanges() 时自动更新相关实体?
【发布时间】:2021-09-17 05:24:02
【问题描述】:

我有两个具有一对多关系的实体。 SamuraisQuotes。一个武士可以有很多行情。

我在Samurai 表和Quote 表上都有一个DateModified 列。

我知道如何使用ChangeTracker 来遍历所有被跟踪的实体并发现哪些实体已被添加或修改。我在下面的SaveChanges() 方法中这样做:

public override int SaveChanges()
{
    DateTime saveTime = DateTime.UtcNow;

    // Update the createdDate and modifiedDate for all added entities
    foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Added))
    {
        if (entry.Entity.GetType().GetProperty("CreatedDate") != null && (DateTime)entry.Property("CreatedDate").CurrentValue == DateTime.MinValue)
            entry.Property("CreatedDate").CurrentValue = saveTime;

        if (entry.Entity.GetType().GetProperty("ModifiedDate") != null)
            entry.Property("ModifiedDate").CurrentValue = saveTime;
    }

    // Update the modifiedDate for all modified entities
    foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified))
    {
        if (entry.Entity.GetType().GetProperty("ModifiedDate") != null)
            entry.Property("ModifiedDate").CurrentValue = saveTime;
    }

    return base.SaveChanges();
}

当我将Quote 添加到Samurai 并调用SaveChanges() 时,仅添加了Quote。相关的Samurai 实体保持不变。如何访问相关的Samurai 实体并将EntityState 更改为已修改,以便我上面的代码将更新其DateModified 列?

【问题讨论】:

  • 你会用这个修改后的武士做什么?
  • @CaiusJard 我不太明白你的问题。我将使用 modifiedDate 来跟踪增量变化。
  • 但是 Samirai 没有改变,Quote 有.. 除非您制定业务规则,即对 Wuote 的更改就是对 Samurai 的更改,在这种情况下,我的问题是“为什么?”或者“你将如何处理这些信息?”例如,如果您想显示最近“因为 wuote 被更改而更改”的 samurai 的前 10 个列表,您可以只要求 db 获取每个 samurai 的最大报价日期,并为您提供前 10 个最近的最大报价日期;您不需要将其复制到武士中

标签: c# .net entity-framework-core


【解决方案1】:

这是正常的。 Samurai 实体尚未更新,这意味着 ChangeTracker 目前根本不知道有关 Samurai 的任何信息。

目前我能想到的唯一解决方案是在调用 SaveChanges 之前设法访问 Samurai,并将其标记为已修改。在这种情况下,ChangeTracker 将捕获并更新 Samurai 的ModifiedDate

// manually mark the samurai as an entity that has been modified
dbContext.Update(samurai); 
dbcontext.SaveChanges();

另外,我认为一个好的做法是引入一个具有 CreatedDateModifiedDate 属性的接口,以及 Samurai 和 Quote 来实现它,因此您不必使用反射(这很昂贵 +太复杂)在 SaveChanges 逻辑中。

// Update the modifiedDate for all modified entities
foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified && e.Entity is ITrackableDate))
{
    (entry as ITrackableDate).ModifiedDate.CurrentValue = saveTime;
}

【讨论】:

    【解决方案2】:

    如果我没记错的话,那么在一对多关系中您没有修改关系的“一”侧 - 您正在通过 ID 链接的“多”侧创建一个新条目 - EF Core 将正确标记创建的新“报价”条目和“武士”将保持不变。

    您可以尝试手动将相应的 Samurai 标记为“已修改”(您也可以手动设置修改日期 - 强制更新被跟踪实体 - 但我不确定这是否适用于影子属性)。

    在这种情况下,我的方式是在 // Update the createdDate and modifiedDate for all added entities 循环中的 SaveChanges 中获取相应的“Samurai” id 并将它们标记为修改/更新修改日期。

    【讨论】:

    • 我同意工作流程。但是如何访问相关的 Samurai 实体?
    • 理论上您可以创建一个虚拟的断开连接的Samurai 实体,其中只有id 由来自相应Quote 的数据填充。然后将此实体附加到更改跟踪器并将其状态设置为“未更改”。接下来,修改modifiedDate - 它将仅标记此属性为已更改 - 调用保存更改后,它将被更新。
    猜你喜欢
    • 2014-07-22
    • 1970-01-01
    • 2017-08-01
    • 2018-02-27
    • 1970-01-01
    • 2020-08-06
    • 2014-11-18
    • 2017-02-11
    • 1970-01-01
    相关资源
    最近更新 更多