EF2.2核心2.2审计返回相同的旧值和新值该如何修复?

3

我正在尝试在我的.Net Core(2.2)中使用EF 2.2 Code First实现一个审计表。我的意图是记录实体中所做的所有更改。我遵循这篇博客文章来实现。一切看起来都很好,但我得到了相同的旧值和新值。

请帮助我找出我的错误。

这是我的控制器,我只分享其中一部分。

 public class ProductController : Controller
    {
        private readonly MyDBContext _context;
        private readonly IProduct productRepository;

public ProductController(MyECODBContext context,IProduct product)
        {
            _context = context;
            productRepository = product;
        }
//My Edit function
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("//my other bindings")] ECOViewModel vmECO,
            string[] ApproversList, string[] ValidatorsList)
{ //POST method of the Edit Page
                   ////My other logic 

   _context.Update(existingProduct);//updating product table
   await _context.SaveChangesAsync(true);

        }
}

以下是来自我的上下文类的审核跟踪代码[此代码来自该博客文章]。 在 switch case 中的 case EntityState.Modified:,我得到了相同的值,即 property.OriginalValue 和 property.CurrentValue。

public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
        {
            var auditEntries = OnBeforeSaveChanges();
            var result = await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
            await OnAfterSaveChanges(auditEntries);
            return result;
        }

        private List<AuditEntry> OnBeforeSaveChanges()
        {
            ChangeTracker.DetectChanges();
            var auditEntries = new List<AuditEntry>();
            foreach (var entry in ChangeTracker.Entries())
            {
                if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
                    continue;

                var auditEntry = new AuditEntry(entry);
                auditEntry.TableName = entry.Metadata.Relational().TableName;
                auditEntries.Add(auditEntry);

                foreach (var property in entry.Properties)
                {
                    if (property.IsTemporary)
                    {
                        // value will be generated by the database, get the value after saving
                        auditEntry.TemporaryProperties.Add(property);
                        continue;
                    }

                    string propertyName = property.Metadata.Name;
                    if (property.Metadata.IsPrimaryKey())
                    {
                        auditEntry.KeyValues[propertyName] = property.CurrentValue;
                        continue;
                    }

                    switch (entry.State)
                    {
                        case EntityState.Added:
                            auditEntry.NewValues[propertyName] = property.CurrentValue;
                            break;

                        case EntityState.Deleted:
                            auditEntry.OldValues[propertyName] = property.OriginalValue;
                            break;

                        case EntityState.Modified:
                            if (property.IsModified)
                            {
                              auditEntry.OldValues[propertyName] = property.OriginalValue;
                              auditEntry.NewValues[propertyName] = property.CurrentValue;
                            }
                            break;
                    }
                }
            }

            // Save audit entities that have all the modifications
            foreach (var auditEntry in auditEntries.Where(_ => !_.HasTemporaryProperties))
            {
                Audits.Add(auditEntry.ToAudit());
            }

            // keep a list of entries where the value of some properties are unknown at this step
            return auditEntries.Where(_ => _.HasTemporaryProperties).ToList();
        }

        private Task OnAfterSaveChanges(List<AuditEntry> auditEntries)
        {
            if (auditEntries == null || auditEntries.Count == 0)
                return Task.CompletedTask;

        foreach (var auditEntry in auditEntries)
            {
                // Get the final value of the temporary properties
                foreach (var prop in auditEntry.TemporaryProperties)
                {
                    if (prop.Metadata.IsPrimaryKey())
                    {
                        auditEntry.KeyValues[prop.Metadata.Name] = prop.CurrentValue;
                    }
                    else
                    {
                        auditEntry.NewValues[prop.Metadata.Name] = prop.CurrentValue;
                    }
                }

                // Save the Audit entry
                Audits.Add(auditEntry.ToAudit());
            }

            return SaveChangesAsync();
        }
    }
1个回答

2

这是一个已知的问题,在帖子的评论部分甚至有提到。为了以后参考,似乎以下方法对一些人有效:

谢谢您的帖子!我尝试使用它并想建议改进如何检测更新。在 Core EF 2.2 上,即使字段未被修改,EntityState.Modified 的状态也为 true,因此我添加了一些代码:

即使没有修改,状态看起来也被修改了,所以通过这种方式可以过滤掉不真实的情况。

case EntityState.Modified:
    if (property.IsModified)
    {
        if(property.OriginalValue == null && property.CurrentValue == null)
          continue;

        if(property.OriginalValue == null ||
           property.CurrentValue == null ||
           !property.OriginalValue.Equals(property.CurrentValue))
        {
            auditEntry.OldValues[propertyName] = property.OriginalValue;
            auditEntry.NewValues[propertyName] = property.CurrentValue;
        }

这个问题看来,你需要额外调用数据库才能成功实现你想要的目标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接