显示原始值实体框架7

时间:2015-09-15 23:52:34

标签: c# .net entity-framework entity-framework-core

我有一个跟踪已添加,已删除和已修改的审核表。我在实体框架内跟踪这个而不是使用数据库触发器有多种原因,但实际上是因为我们使用了一个进程账户,我想跟踪用户实际对该记录进行了哪些更改。

我使用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不包含OriginalValues的定义。我要拔掉头发......如何从EF 7的修改对象中获取原始值?

3 个答案:

答案 0 :(得分:12)

// 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}");
}

答案 1 :(得分:1)

另一种选择是仍然使用 OriginalValues ,但使用属性代替 PropertyNames 。这将使foreach循环过程类型为 Microsoft.EntityFrameworkCore.Metadata.IProperty GetValues 方法具有接受 IProperty 的重载,因此这些调用的代码不需要更改,但您需要更改 ColumnName 分配从 propertyName 属性名称

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()
        });
    }
}

答案 2 :(得分:-1)

这可以通过这个方法 dbEntry.GetDatabaseValues() 解决。 示例代码在下面提到。

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