Entity Framework DbContext SaveChanges () Исходное значение Неверно - PullRequest
6 голосов
/ 06 марта 2012

Я пытаюсь реализовать AuditLog с использованием EF 4.1, переопределяя метод SaveChanges (), как обсуждалось в следующих местах:

У меня проблемы с "измененными" записями. Всякий раз, когда я пытаюсь получить значение OriginalValue соответствующего свойства, оно всегда имеет то же значение, что и в поле CurrentValue .

Сначала я использую этот код, и он успешно определяет измененные записи:

public int SaveChanges(string userID)
{

    // Have tried both with and without the following line, and received same results:
    // ChangeTracker.DetectChanges();

    foreach (
      var ent in this.ChangeTracker
                     .Entries()
                     .Where(p => p.State == System.Data.EntityState.Added
                                     p.State == System.Data.EntityState.Deleted             
                                     p.State == System.Data.EntityState.Modified))
    {
        // For each change record, get the audit record entries and add them
        foreach (AuditLog log in GetAuditRecordsForChange(ent, userID))
        {
            this.AuditLog.Add(log);
        }

    }

    return base.SaveChanges();
}

Проблема заключается в следующем (сокращенный код):

    private List<AuditLog> GetAuditRecordsForChange(DbEntityEntry dbEntry, string userID)
    {
        if (dbEntry.State == System.Data.EntityState.Modified)
        {
            foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
            {
                if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName),
                    dbEntry.CurrentValues.GetValue<object>(propertyName)))
                {
                        // It never makes it into this if block, even when
                        //    the property has been updated.
                }

                // If I updated the property "Name" which was originally "OldName" to the value "NewName" and then break here and inspect the values by calling:
                //      ?dbEntry.OriginalValues.GetValue<object>("Name").ToString()

                // the result will be "NewName" and not "OldName" as expected
             }
         }
    }

Странно то, что звонок на dbEntry.Property(propertyName).IsModified(); будет верните истину в этом случае. Просто у OriginalValue нет ожидаемого значения внутри. Кто-нибудь хотел бы помочь указать мне правильное направление? Я не могу заставить это работать правильно.

Ответы [ 3 ]

13 голосов
/ 09 марта 2012

Если вы измените

dbEntry.OriginalValues.GetValue<object>(propertyName);

на

dbEntry.GetDatabaseValues().GetValue<object>(propertyName);

, то это сработает.

13 голосов
/ 07 марта 2012

Когда EF извлекает объект из базы данных, он делает снимок исходных значений для всех свойств этого объекта. Позже, когда будут внесены изменения в значения этих свойств, исходные значения останутся такими же, пока текущие значения изменятся.

Однако, чтобы это произошло, EF должен отслеживать объект на протяжении всего процесса. В веб-приложении или другом n-уровневом приложении обычно значения отправляются клиенту, и контекст, используемый для запроса объекта, удаляется. Это означает, что объект больше не отслеживается EF. Это хорошая и хорошая практика.

Как только приложение отправляет обратно, сущность реконструируется с использованием значений из клиента, а затем повторно присоединяется к контексту и устанавливается в состояние Modified . Однако по умолчанию единственными значениями, которые возвращаются от клиента, являются текущие значения. Исходные значения теряются. Обычно это не имеет значения, если вы не выполняете оптимистичный параллелизм или не хотите быть очень осторожным в обновлении только тех значений, которые действительно изменились. В этих случаях исходные значения также следует отправлять клиенту (обычно в виде скрытых полей в веб-приложении), а затем повторно применять в качестве исходных значений как часть процесса присоединения. В приведенном выше примере этого не произошло, и поэтому исходные значения не отображались должным образом.

0 голосов
/ 12 января 2019

Я получил эту ошибку, когда переопределяю SaveChanges в контексте следующим образом

public override int SaveChanges()
    {
        var changeInfo = ChangeTracker.Entries()
            .Select(t => new {
                Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
                Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
            }).ToList();
        return base.SaveChanges();
    }

и когда я очистил это исправлено!

ChangeTracker.Entries (). ToList () в SaveChanges неверно ...

...