I've seen all the questions out there for tracking changes to an entity, but none of those solutions included navigation properties. Is this even possible? I don't need some SUPER generic solution that just logs everything. I only want things tracked for specific "main" entities. And the audit log is going to be a human readable custom one, so not just some table that has oldData newData like I have seen in the examples on here.
I've gotten it almost to a good point except tracking the navigation properties, I have an Interface on the POCO's service that determines whether I want to track changes, then in my entityService.Save
method I have this check:
var trackChangesService = this as ITrackChangesService<TClass>;
if (trackChangesService != null)
{
TClass oldEntity = Repository.GetOldEntity(entity);
trackChangesService.SaveChanges(entity, oldEntity);
}
The save changes method is what the ITrackChanges interface exposes and will have custom logic on a per entity basis (this includes email notifications, etc.), but the problem is I can't propertly get the oldEntity. Currently the method looks like this:
public TClass GetOldEntity(TClass entity)
{
//DbEntityEntry<TClass> oldEntry = Context.Entry(entity);
////oldEntry.CurrentValues.SetValues(oldEntry.OriginalValues);
//var values = oldEntry.OriginalValues;
//return (TClass)oldEntry.GetDatabaseValues().ToObject();
return Context.Set<TClass>().AsNoTracking().FirstOrDefault(x => x.Id == entity.Id);
}
You can see the code I have been playing with. I can get the regular properties old and new values fine, but the navigation properties do not carry over. But I need this information, say for instance I am editing a user and on the edit user screen, groups can be removed and added. When the save button is clicked, it performs those updates.
So my update view look like this:
private UserSaveModel Update(Guid id, UserSaveModel userSaveModel)
{
User user = _userService.GetOne(x => x.Id == id);
user = _userService.ConvertFromSaveModel(userSaveModel, user);
_userService.Save(user);
return userSaveModel;
}
I guess one way to look at the problem is, I am adjusting the values on the entity on the context in .ConvertFromSaveeModel()
on the existing user record, including the navigation properties, so once I call save, that old navigation property data is gone.
Is there anyway to get original navigation property information for an entity using this workflow? If not, how can I change the workflow to make this possible? If I don't query the user object at the beginning and instead make one from scratch, some data that may not be exposed in the viewModel won't pass over, so I am not sure that will work. Any other suggestions? Maybe clone the entity and use that as original before I made changes? Does that carry over navigation properties?