Cezary Rynkowski Cezary Rynkowski - 3 months ago 27
ASP.NET (C#) Question

ChangeTracker.Entries() CurrentValue equals OriginalValue in EF7 (EF Core)

I have a issue in EF7/asp.Net Core application. In my context I create a method Save:

public int Save()
{
ChangeTracker.DetectChanges();
var modifiedEntities = ChangeTracker.Entries()
.Where(p => p.State == EntityState.Modified || p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified || p.State == EntityState.Detached).ToList();
var now = DateTime.UtcNow;

foreach (var change in modifiedEntities)
{
var entityName = change.Entity.GetType().Name;
var primaryKeyValue = GetPrimaryKeyValue(change.Entity);
foreach (var prop in change.Entity.GetType().GetTypeInfo().DeclaredProperties)
{
if (!prop.GetGetMethod().IsVirtual)
{
var currentValue = change.Property(prop.Name).CurrentValue;
var originalValue = change.Property(prop.Name).OriginalValue;
if (originalValue.ToString() != currentValue.ToString())
{
var changeLoged = new ChangeLog
{
PropertyName = prop.Name,
EntityName = entityName,
PrimaryKeyValue = primaryKeyValue,
DateChange = now,
OldValue = originalValue.ToString(),
NewValue = currentValue.ToString(),
ChangedBy = "test"
};
ChangeLog.Add(changeLoged);
}
}
}
}
return base.SaveChanges();
}


and method GetPrimaryKeyValue:

protected virtual int GetPrimaryKeyValue<T>(T entity)
{
var test = entity;
var test2 = test.GetType();
var keyName = this.Model.FindEntityType(test2).FindPrimaryKey().Properties
.Select(x => x.Name).Single();
var result = (int)entity.GetType().GetProperty(keyName).GetValue(entity, null);
if (result < 0)
return -1;

return result;
}


Unfortunatlly the change.Property(prop.Name).CurrentValue always equals OriginalValue, so the if
originalValue.ToString() != currentValue.ToString()


always return false.

Answer

This will not exactly answer your question since I cannot reproduce this issue but this may help you.

In EF Core, the PropertyEntry class has now an IsModified property which let you know if the value has been modified or not.

You should use it instead:

if (change.Property(prop.Name).IsModified)
{
    var changeLoged = new ChangeLog
    {
        PropertyName = prop.Name,
        EntityName = entityName,
        PrimaryKeyValue = primaryKeyValue,
        DateChange = now,
        OldValue = originalValue.ToString(),
        NewValue = currentValue.ToString(),
        ChangedBy = "test"
    };
    ChangeLog.Add(changeLoged);
}

Disclaimer: I'm the owner of the project Entity Framework Plus

The Library have an Audit Feature (Supporting EF Core) which you may use or inspire to create your auditing (The code is Open Source).

Documentation: EF+ Audit

Comments