2015-09-15 3 views
3

У меня есть таблица аудита, в которой отслеживаются Добавленные, Удаленные и Модифицированные. Я отслеживаю это внутри Entity Framework вместо использования триггера Database по нескольким причинам, но на самом деле потому, что мы используем учетную запись Process, и я хочу отслеживать, какой пользователь физически сделал это изменение для этой записи.Показать исходные значения Entity Framework 7

У меня было это работает с EF 5 & Я не помню, возможно, он работал в EF6. В любом случае я испытываю самое сложное время, когда EF 7 пытается захватить исходные значения.

Я заметил, что когда я нахожусь в часах - я могу видеть оригинальные ценности внутри Непубличных участников - так что в голове я знаю, что он должен где-то существовать.

В конечном итоге это работает внутри EF более ранние версии:

EntityEntry dbEntry; //this is actually passed in a different area just showing as an example. 

foreach (string propertyName in dbEntry.OriginalValues.PropertyNames) 
{ 
    // For updates, we only want to capture the columns that actually changed 
    if (!object.Equals(dbEntry.OriginalValues.GetValue<object>(propertyName), dbEntry.CurrentValues.GetValue<object>(propertyName))) 
    { 
     result.Add(new TableChange() 
     { 
      AuditLogID = Guid.NewGuid(), 
      UserID = userId, 
      EventDateUTC = changeTime, 
      EventType = "M", // Modified 
      TableName = tableName, 
      RecordID = dbEntry.OriginalValues.GetValue<object>(keyName).ToString(), 
      ColumnName = propertyName, 
      OriginalValue = dbEntry.OriginalValues.GetValue<object>(propertyName) == null ? null : dbEntry.OriginalValues.GetValue<object>(propertyName).ToString(), 
      NewValue = dbEntry.CurrentValues.GetValue<object>(propertyName) == null ? null : dbEntry.CurrentValues.GetValue<object>(propertyName).ToString() 
     } 
     ); 
     } 
} 

Ошибка я получаю это EntityEntry не содержит defition для OriginalValues. Я собираюсь вытащить свои волосы ... Как получить исходные значения из измененного объекта с помощью EF 7?

+0

есть [DbEntityEntry] (https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry (v = vs.113) .aspx), который содержит ' OriginalValues'. вы можете получить его с помощью метода [DbContext.Entry ] (https://msdn.microsoft.com/en-us/library/gg696578 (v = vs.113) .aspx). – ieaglle

+1

@ieaglle that's EntityFramework 5/6 –

+0

О, правильно, тогда ваш ответ правильный. [PropertyEntry] (https://github.com/aspnet/EntityFramework/blob/868794f6ab99ff1681a09a2a5e307a742e9d0526/src/EntityFramework.Core/ChangeTracking/PropertyEntry%60.cs) содержит 'OriginalValue' и [EntityEntry] (https://github.com). /aspnet/EntityFramework/blob/868794f6ab99ff1681a09a2a5e307a742e9d0526/src/EntityFramework.Core/ChangeTracking/EntityEntry.cs) содержит метод [Свойства] (https://github.com/aspnet/EntityFramework/blob/868794f6ab99ff1681a09a2a5e307a742e9d0526/src/EntityFramework.Core/ChangeTracking /EntityEntry.cs#L91), который возвращает 'PropertyEntry'. – ieaglle

ответ

11
// using System.Reflection; 
foreach (var property in dbEntry.Entity.GetType().GetTypeInfo().DeclaredProperties) 
{ 
    var originalValue = dbEntry.Property(property.Name).OriginalValue; 
    var currentValue = dbEntry.Property(property.Name).CurrentValue; 
    Console.WriteLine($"{property.Name}: Original: {originalValue}, Current: {currentValue}"); 
} 
+0

Какой синтаксис включает префикс '$' это? какая-то новая особенность C# 6.0? – Hopeless

+3

@Hopeless, Yup. Это называется [Интерполяция строк] (https://msdn.microsoft.com/en-us/library/dn961160.aspx). – ieaglle

+2

Как всегда, рекомендуется обрабатывать ошибки. 'dbEntry.Property (property.Name)' будет вызывать InvalidOperationException, если класс сущности содержит свойства, которые не включены в модель, например, посредством аннотации '[NotMapped]', как показано [здесь] (http: // ef.readthedocs.org/en/latest/modeling/included-properties.html). Вы можете вместо этого выполнить цикл над 'entry.Metadata.GetProperties()', если вы хотите только рассмотреть свойства, отображаемые в модели. Вероятно, это также должно работать для [теневых свойств] (http://ef.readthedocs.org/en/latest/modeling/shadow-properties.html), но я не пытался. – takrl

0

Другой вариант по-прежнему использовать OriginalValues ​​, но вместо PropertyNames используйте Свойства. Это сделает типы процессов цикла foreach Microsoft.EntityFrameworkCore.Metadata.IProperty. GetValues ​​ метод имеет перегрузку, которая принимает IProperty, поэтому никаких изменений, необходимых в коде для этих вызовов, но вам нужно будет изменить ColumnName задание от ИмениСвойства в собственности . Наименование.

foreach (var property in entityEntry.OriginalValues.Properties) 
{ 
    if (!object.Equals(entityEntry.OriginalValues.GetValue<object>(property), 
     entityEntry.CurrentValues.GetValue<object>(property))) 
    { 
     result.Add(
      new AuditLog() 
      { 
       UserId = userId, 
       EventDate = changeTime, 
       EventType = "M", 
       TableName = tableName, 
       RecordId = entityEntry.OriginalValues.GetValue<object>(keyName).ToString(), 
       ColumnName = property.Name, 
       OriginalValue = 
        entityEntry.OriginalValues.GetValue<object>(property) == null 
        ? null 
        : entityEntry.OriginalValues.GetValue<object>(property).ToString(), 
       NewValue = 
        entityEntry.CurrentValues.GetValue<object>(property) == null 
        ? null 
        : entityEntry.CurrentValues.GetValue<object>(property).ToString() 
     }); 
    } 
} 
Смежные вопросы