1

我正在尝试首先使用 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 的 switch 案例中:我得到的 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();
        }
    }
4

1 回答 1

1

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

谢谢你的文章!我已经尝试使用它,并想建议改进如何检测更新。在 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;
        }

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

于 2019-12-01T07:51:24.607 回答