Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Very, very rough idea:</p> <pre><code>foreach (var property in dbEntityEntry.Entity.GetType().GetProperties()) { DbPropertyEntry propertyEntry = dbEntityEntry.Property(property.Name); if (propertyEntry.IsModified) { Log.WriteAudit("Entry: {0} Original :{1} New: {2}", property.Name, propertyEntry.OriginalValue, propertyEntry.CurrentValue); } } </code></pre> <p>I have no clue if this would really work in detail, but this is something I would try as a first step. Of course there could be more then one property which has changed, therefore the loop and perhaps multiple calls of <code>WriteAudit</code>.</p> <p>The reflection stuff inside of SaveChanges could become a performance nightmare though.</p> <p><strong>Edit</strong></p> <p>Perhaps it is better to access the underlying <code>ObjectContext</code>. Then something like this is possible:</p> <pre><code>public class TestContext : DbContext { public override int SaveChanges() { ChangeTracker.DetectChanges(); // Important! ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext; List&lt;ObjectStateEntry&gt; objectStateEntryList = ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted) .ToList(); foreach (ObjectStateEntry entry in objectStateEntryList) { if (!entry.IsRelationship) { switch (entry.State) { case EntityState.Added: // write log... break; case EntityState.Deleted: // write log... break; case EntityState.Modified: { foreach (string propertyName in entry.GetModifiedProperties()) { DbDataRecord original = entry.OriginalValues; string oldValue = original.GetValue( original.GetOrdinal(propertyName)) .ToString(); CurrentValueRecord current = entry.CurrentValues; string newValue = current.GetValue( current.GetOrdinal(propertyName)) .ToString(); if (oldValue != newValue) // probably not necessary { Log.WriteAudit( "Entry: {0} Original :{1} New: {2}", entry.Entity.GetType().Name, oldValue, newValue); } } break; } } } } return base.SaveChanges(); } } </code></pre> <p>I've used this myself in EF 4.0. I cannot find a corresponding method to <code>GetModifiedProperties</code> (which is the key to avoid the reflection code) in the <code>DbContext</code> API.</p> <p><strong>Edit 2</strong></p> <p><strong>Important</strong>: When working with POCO entities the code above needs to call <code>DbContext.ChangeTracker.DetectChanges()</code> at the beginning. The reason is that <code>base.SaveChanges</code> is called too late here (at the end of the method). <code>base.SaveChanges</code> calls <code>DetectChanges</code> internally, but because we want to analyze and log the changes before, we must call <code>DetectChanges</code> manually so that EF can find all modified properties and set the states in the change tracker correctly.</p> <p>There are possible situations where the code can work without calling <code>DetectChanges</code>, for example if DbContext/DbSet methods like <code>Add</code> or <code>Remove</code> are used after the last property modifications are made since these methods also call <code>DetectChanges</code> internally. But if for instance an entity is just loaded from DB, a few properties are changed and then this derived <code>SaveChanges</code> is called, automatic change detection would not happen before <code>base.SaveChanges</code>, finally resulting in missing log entries for modified properties.</p> <p>I've updated the code above accordingly.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload