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

c#, dbcontext, ef-code-first, logging, repository

Solution

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.

Problem

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).

Original source

Related problems