首页 > 解决方案 > 如何在保存之前附加新实体?

问题描述

我试图在 EF Core 中调用 SaveChanges 之前将新实体附加到更改跟踪器。OnBeforeSaving()我目前在 DbContext中自己的方法中修改了一些属性:

private void OnBeforeSaving()
{
    var entries = ChangeTracker.Entries();
    var utcNow = DateTime.UtcNow;

    foreach (var entry in entries)
    {
        if (entry.Entity is MyObject trackable)
        {
            switch (entry.State)
            {
                case EntityState.Modified:
                    trackable.UpdatedOn = utcNow;
                    break;
                    case EntityState.Added:
                    trackable.CreatedOn = utcNow;
                    break;
            }

            AddNewObject();
        }
                
    }
}

我有一个在添加/更新时需要填充的对象

  1. 很高兴分享逻辑而不是在创建和更新页面上复制它
  2. 需要知道 CreatedOn/UpdatedOn 值

在该方法中,我尝试将对象添加到更改跟踪器,但由于我正在迭代AddNewObject()更改跟踪器而引发异常。InvalidOperationException: Collection was modified; enumeration operation may not execute.

private void AddNewObject(MyObject myObject) 
{
    var newObject = NewObject()
    {
         propOne = myObject.CreatedOn,
         propTwo = myObject.OtherProp
    }

    ChangeTracker.Context.Attach(newObject).State = EntityState.Added;
}

有没有办法在保存之前从 DbContext 附加一个新实体?

标签: c#entity-frameworkentity-framework-core

解决方案


在实现类似审计功能以报告更改时,它可以帮助将审计功能隔离到单独的有界 DbContext 中,该 DbContext 仅处理审计实体/w 相关字段和 FK(如果适用)审计代码将使用这个完全独立的 DbContext 实例只关心带有填充字段的审计行实体,因此不会影响主应用程序 DbContext 上的更改跟踪器。

当涉及到审计变更实施时,可以通过多种方式完成。为了避免编写特定于实体的实现或强制转换来访问属性,您可以选择使用实体的ChangeTracker表示而不是实体本身来构建您的审计记录。(获取属性名称、旧值和新值)另一种选择是将实体序列化为 JSON 或 XML,以作为时间点快照,以及存储在记录中的适用 PK/Type 信息。在查看更改时,这可能涉及更多的检查处理,但这通常可以提供,因为应用程序将查询此信息以在任何给定时间显示少量记录。(即给定记录的更改历史记录)


推荐阅读