繁体   English   中英

EF2.2 Core 2.2 审计返回相同的新旧值如何解决?

[英]EF2.2 Core 2.2 Auditing returns same old and new value how to fix?

我正在尝试首先使用 EF 2.2 代码在我的 .net 核心 (2.2) 中实现审计表。 我的目的是记录在我跟随这篇博客文章实施的实体中所做的所有更改。 一切似乎都很好,但我得到了相同的新旧价值。

请帮我找出我的错误。

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

 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);

        }
}

以及来自我的上下文类的审计跟踪代码[此代码来自那篇博客文章] 在案例 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();
        }
    }

这是一个已知问题,甚至在帖子的评论部分中也提到过。 以供将来参考,以下内容似乎对某些人有用

谢谢你的文章! 我已经尝试使用它,并想建议改进如何检测更新。 在 Core EF 2.2 EntityState.Modified 上,即使字段没有被修改,也为真,所以我添加了一些代码:

即使状态未修改,状态看起来也已修改,因此您可以通过这种方式过滤掉不真实的情况。

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;
        }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM