EF7 - How to get values from DbSet before change

asp.net c# entity-framework entity-framework-core linq

Question

I try to get the value of entity that stored in DbSet before it was changed by code and before it was saved. However, when I try to get it with LINQ Single statement I get the changed value. I'm using EF7.

Here's the code:

DbSet<Entity> dbSet = Context.dbSet;
Entity ent = dbSet.Single(x => x.Id == id);
ent.FirstName = "New name";
Entity entityBeforeChange = dbSet.Single(x => x.Id == id);  //here I want to get entity with old values, if that's important I just need to read it without modifying this instance

Context.SaveChanges();

Hope I was clear enough and can get some help

2
2
1/28/2016 1:56:28 PM

Accepted Answer

You can Detach an entity from the context. Keep in mind that you'll have to pull it from the context before you update the other, attached entity.

DbSet<Entity> dbSet = Context.dbSet;
Entity ent = dbSet.Single(x => x.Id == id);
Entity entityBeforeChange = dbSet.Single(x => x.Id == id); 
Context.Entry(entityBeforeChange).State = EntityState.Detached; // severs the connection to the Context
ent.FirstName = "New name";

Context.SaveChanges();
1
1/28/2016 2:10:38 PM

Expert Answer

Here is a code I use from my audit library.

EF7

using (var ctx = new TestContext())
{
    Entity ent = entity.Single(x => x.Id == id);
    entity.FirstName = "New name";

    context.ChangeTracker.DetectChanges();

    // Find your entry or get all changed entries
    var changes = context.ChangeTracker.Entries().Where(x => x.State == EntityState.Modified);

    foreach (var objectStateEntry in changes)
    {
        AuditEntityModified(audit, objectStateEntry, auditState);
    }
}

public static void AuditEntityModified(Audit audit, AuditEntry entry, EntityEntry objectStateEntry)
{
    foreach (var propertyEntry in objectStateEntry.Metadata.GetProperties())
    {
        var property = objectStateEntry.Property(propertyEntry.Name);

        if (entry.Parent.CurrentOrDefaultConfiguration.IsAudited(entry.ObjectStateEntry, propertyEntry.Name))
        {
            entry.Properties.Add(new AuditEntryProperty(entry, propertyEntry.Name, property.OriginalValue, property.CurrentValue));
        }
    }
}

EF6

using (var ctx = new TestContext())
{
    Entity ent = entity.Single(x => x.Id == id);
    entity.FirstName = "New name";

    var entry = ((IObjectContextAdapter)ctx).ObjectContext.ObjectStateManager.GetObjectStateEntry(entity);
    var currentValues = entry.CurrentValues;
    var originalValues = entry.OriginalValues;

    AuditEntityModified(originalValues, currentValues);
}

public static void AuditEntityModified(DbDataRecord orginalRecord, DbUpdatableDataRecord currentRecord, string prefix = "")
{
    for (var i = 0; i < orginalRecord.FieldCount; i++)
    {
        var name = orginalRecord.GetName(i);
        var originalValue = orginalRecord.GetValue(i);
        var currentValue = currentRecord.GetValue(i);

        var valueRecord = originalValue as DbDataRecord;
        if (valueRecord != null)
        {
            // Complex Type
            AuditEntityModified(valueRecord, currentValue as DbUpdatableDataRecord, string.Concat(prefix, name, "."));
        }
        else
        {
            if (!Equals(currentValue, originalValue))
            {
                // Add modified values
            }
        }
    }
}

Edit: The complete source code can be found in my GitHub repository: https://github.com/zzzprojects/EntityFramework-Plus

Library Website: http://entityframework-plus.net/

2
2/21/2018 2:37:37 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow