EF ObjectStateEntry OriginalValues包含CurrentValues

时间:2015-02-05 12:53:19

标签: c# entity-framework audit objectstatemanager

我正在尝试覆盖实体框架的SaveChanges()方法以保存审核信息。我从以下开始:

public override int SaveChanges()
{
    ChangeTracker.DetectChanges();
    ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;
    List<ObjectStateEntry> objectStateEntryList = ctx.ObjectStateManager.GetObjectStateEntries(
                                                         EntityState.Added
                                                       | EntityState.Modified
                                                       | EntityState.Deleted).ToList();

    foreach (ObjectStateEntry entry in objectStateEntryList)
    {
        if (!entry.IsRelationship)
        {
            //Code that checks and records which entity (table) is being worked with
            ...

            foreach (string propertyName in entry.GetModifiedProperties())
            {
                DbDataRecord original = entry.OriginalValues;
                string oldValue = original.GetValue(original.GetOrdinal(propertyName)).ToString();

                CurrentValueRecord current = entry.CurrentValues;
                string newValue = current.GetValue(current.GetOrdinal(propertyName)).ToString();

                if (oldValue != newValue)
                {
                    AuditEntityField field = new AuditEntityField
                    {
                        FieldName = propertyName,
                        OldValue = oldValue,
                        NewValue = newValue,
                        Timestamp = auditEntity.Timestamp
                    };
                    auditEntity.AuditEntityField.Add(field);
                }
            }
        }
    }
}

我遇到的问题是我在entry.OriginalValuesentry.CurrentValues中获得的值始终是新的更新值:

Audit Entity State

3 个答案:

答案 0 :(得分:1)

已发现问题:

public ActionResult Edit(Branch branch)
{
    if (ModelState.IsValid)
    {
        db.Entry(branch).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(branch);
}

以上述方式保存更新似乎会导致ChangeTracker无法获取旧值。我通过简单地使用ViewModels来解决所有必需的更新:

public ActionResult Edit(BranchViewModel model)
{
    if (ModelState.IsValid)
    {
        Branch branch = db.Branch.Find(model.BranchId);

        if (branch.BranchName != model.BranchName)
        {
            branch.BranchName = model.BranchName;
            db.SaveChanges();
        }
        return RedirectToAction("Index");
    }
    return View(model);
}

答案 1 :(得分:0)

要从数据库中获取旧值的副本而不更新EF实体,您可以使用

2018-05-03T13:57:15-04:00

context.Entry(yourEntity).GetDatabaseValues().ToObject()

警告:这确实会引发数据库调用。

答案 2 :(得分:0)

对我来说最简单的方法是:

var cadastralAreaDb = await _context.CadastralAreas.FindAsync(id).ConfigureAwait(false);

  var audit = new Audit
  {
     CreatedBy = "Edi"
   };

_context.Entry(cadastralAreaDb).CurrentValues.SetValues(cadastralArea);
await _context.SaveChangesAsync(audit).ConfigureAwait(false);

这已在ASP NET Core 3.1中进行了测试