I'm using EF code first. Also i'm using a base Repository for all my repositories and an IUnitofWork
that inject to the repositories:
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(before save occurs) values also changed values(after save occurs).
you have scared people away with the extra requirement
This is simply a non trivial exercise. And if this is important, you should manage/track changes across references with code.
this is a sample covering this topic Undo changes in entity framework entities
There is a sample doing close top what you want here undo changes It can easily be converted to load before and after images elsewhere.
Given the ObjectState entry after DetectChanges is called, you can implement a simple entity by entity option. and per UOW. But the navigation / references version makes this very complex as you worded the requirement.
EDIT : How to access the changeList
I have overridded the default SaveChanges method to log changes for add/update/delete in entity. Though it does not cover navigation property changes.
Based on this article: Using entity framework for auditing
DbContext has ChangeTracker property. You can override .SaveChanges() in your context and log changes. I don't think that entity framework can do it for you. Probably, you must detect changes directly in your model classes.
You can get the before and after values for all changed entities by going through
DbContext.ChangeTracker
. Unfortunately the API is a little verbose: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 theDbPropertyValues
(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.