У меня проблема с обновлением сущностей в EF Core и затем , регистрирующим эти изменения в таблице . Используемые технологии:
- .NET Core 2.2.0
- EF Core 2.2.3
Итак, я хочу получить сущность из базы данных, отредактировать ее во внешнем интерфейсе, а затем обновить в бэкэнде и сохранить эти изменения в базе данных. Кроме того, у меня есть таблица с именем ChangeLogs
, где наиболее важными полями являются From (сопоставлено с OldValues
) и To (сопоставлено с CurrentValues
). Итак, эти два поля одинаковы (имеется в виду, что они имеют одинаковые значения, новые значения), и ситуация выглядит следующим образом:
Я получаю сущность из базы данных вот так
_context.Anomalies
.Include(a => a.Asset)
.FirstOrDefaultAsync(a => a.Id == anomalyId)
Отредактируйте объект во внешнем интерфейсе, а затем сделайте запрос PUT для его обновления;
Обновить сущность:
Чтобы Update()
заработал, сначала я должен вызвать это:
_context.DetachAllEntities();
В противном случае я получаю сообщение о том, что объект с таким же Id уже отслеживается. Затем позвоните Update()
и SaveChanges()
:
_context.Anomalies.Update(anomaly);
_context.SaveChanges();
Объект anomaly
является объектом запроса.
Для части ChangeLog
я переопределил метод SaveChanges()
, следуя этому примеру , и значения Old / Original и New / Current установлены следующим образом:
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
В основном это проходит через все записи из ChangeTracker
, создает AuditEntry
, а после base.SaveChanges()
он возвращается и устанавливает EntityId для этого AuditEntry, потому что у вас его нет до сохранения изменений (это в Если вы добавляете новую сущность, для обновления ничего не происходит после сохранения изменений).
Метод Update () работает, изменения отражаются в базе данных. Но единственная проблема с ChangeLogs
, запись из ChangeTracker.Entries()
не знает OldValues
.
Я признаю, что не до конца понимаю систему отслеживания, используемую EF, но полагаю, что она должна помочь мне обновлять сущности, а не создавать проблемы. Потому что я знаю, что звонить _context.DetachAllEntities();
не правильно. Я попытался использовать AsNoTracking()
и сбросить DetachAllEntities()
, но результат, кажется, тот же. Я думал о том, чтобы взять dbEntity, скопировать каждое поле из объекта запроса в объект базы данных, а затем Update(dbEntity)
, но, похоже, нужно проделать большую работу, чтобы получить небольшую выгоду. Моя сущность Anomaly
имеет много навигационных свойств, поэтому было бы сложно создать для нее метод копирования и сохранить его.
DetachAllEntities()
определяется следующим образом:
public static void DetachAllEntities(this DbContext context)
{
var entries = context.ChangeTracker.Entries().ToList();
foreach (var entry in entries)
{
entry.State = EntityState.Detached;
}
}
DbContext
установлен на Scoped
срок службы, менеджеры также.
Я пытался использовать метод Auditing из этого урока , но результат тот же.
У меня есть опасение, что весь процесс обновления не выполнен правильно, и поэтому возникают проблемы ..
UPDATE
Я создал пример проекта, чтобы проиллюстрировать эту проблему. Вы можете проверить исходный код на bitbucket . У README есть еще информация об этом
Я сериализовал объекты, извлеченные из контекста.
С отслеживанием на левом <====> Без отслеживания на правом
With NO tracking on the RIGHT">
Любые советы, мнения, новые идеи, комментарии приветствуются. Спасибо!