EF ObjectStateEntry OriginalValues содержит CurrentValues
Я пытаюсь переопределить Entity Framework 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.OriginalValues
И в entry.CurrentValues
всегда новое обновленное значение:
2 ответа
Решение
Проблема была найдена:
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);
}
Чтобы получить копию старых значений из базы данных без обновления сущности EF, вы можете использовать
context.Entry(yourEntity).GetDatabaseValues().ToObject()
или же
yourEntity.GetDatabaseValues().ToObject()
Внимание: это вызывает вызов базы данных.
Самым простым способом для меня было:
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.