Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I log all entities change, during .SaveChanges() using EF code first?

I'm using EF code first. I'm using a base Repository for all my repositories and an IUnitofWork that inject to the repositories, too:

public interface IUnitOfWork : IDisposable {     IDbSet<TEntity> Set<TEntity>() where TEntity : class;     int SaveChanges(); }  public class BaseRepository<T> where T : class {     protected readonly DbContext _dbContext;     protected readonly IDbSet<T> _dbSet;       public BaseRepository(IUnitOfWork uow)     {         _dbContext = (DbContext)uow;         _dbSet = uow.Set<T>();     }     //other methods }    

e.g my OrderRepository is like this:

class OrderRepository: BaseRepository<Order> {     IUnitOfWork _uow;     IDbSet<Order> _order;      public OrderRepository(IUnitOfWork uow)         : base(uow)     {         _uow = uow;         _order = _uow.Set<Order>();     }     //other methods } 

And I use it in this way:

public void Save(Order order) {         using (IUnitOfWork uow = new MyDBContext())         {             OrderRepository repository = new OrderRepository(uow);              try             {                repository.ApplyChanges<Order>(order);                    uow.SaveChanges();             }            }  }      

Is there any way to log change histories of all entities(include their navigation properties) during .SaveChanges()? I want to log original values(before save occurs) and changed values(after save occurs).

like image 500
Masoud Avatar asked Jul 28 '13 03:07

Masoud


People also ask

How do I track changes in Entity Framework?

Tracking from queriesEF Core change tracking works best when the same DbContext instance is used to both query for entities and update them by calling SaveChanges. This is because EF Core automatically tracks the state of queried entities and then detects any changes made to these entities when SaveChanges is called.

What does the DbContext SaveChanges () method return?

Returns. The number of state entries written to the underlying database. This can include state entries for entities and/or relationships.

How do I use SaveChanges in Entity Framework?

The SaveChanges method of the DbContext prepares the Insert , Update & Delete Queries. It does so by tracking the changes to each of the entities' Context is tracking. Whenever we query the database for entities, the Context retrieves them and mark the entity as Unchanged .


1 Answers

You can get the before and after values for all changed entities by going through DbContext.ChangeTracker. Unfortunately the API is a little verbose:

var changeInfo = context.ChangeTracker.Entries()             .Where (t => t.State == EntityState.Modified)             .Select (t => new {                 Original = t.OriginalValues.PropertyNames.ToDictionary (pn => pn, pn => t.OriginalValues[pn]),                 Current = t.CurrentValues.PropertyNames.ToDictionary (pn => pn, pn => t.CurrentValues[pn]),             }); 

You can modify that to include things like the type of the entity if you need that for your logging. There is also a ToObject() method on the DbPropertyValues (the type of OriginalValues and CurrentValues) you could call if you already have a way to log whole objects, although the objects returned from that method will not have their navigation properties populated.

You can also modify that code to get all entities in the context by taking out the Where clause, if that makes more sense given your requirements.

like image 197
Steve Ruble Avatar answered Sep 18 '22 06:09

Steve Ruble