I\'m trying to implement an AuditLog using the DBContext\'s ChangeTracker object, I ran into an issue where the DbEntityEntry.OriginalValues
were getting wiped out
it somehow messes up the ChangeTracker's ability to report on the changes
No it doesn't messes anything. Change tracker ability is based on the fact that change tracker knows the entity prior to making changes. But in your case the change tracker is informed about the entity with changes already applied and POCO entity doesn't keep any information about its original values. POCO entity has only single set of values which is interpreted as both current and original. If you want anything else you must code it yourselves.
Am I supposed to do the latter example
In your simple case yes and you can simply use:
public void SaveProduct(Product product, string userID)
{
if (product.ProductID == 0)
{
context.Products.Add(product);
}
else
{
Product prodToUpdate = context.Products
.Where(p => p.ProductID == product.ProductID).FirstOrDefault();
if (prodToUpdate != null)
{
context.Entry(prodToUpdate).CurrentValues.SetValues(product);
}
}
context.SaveChanges(userID);
}
The problem is that this works only for simple and complex properties. Another problem is that this overwrites all properties so if for example your entity has some field you don't want to show in UI (or don't want to let user to edit the field) you must still set correct current value to your product
instance otherwise that value will be overwritten when applying current values.
The whole situation becomes significantly more complex once you try to apply this to the real scenario. You will fail and you will fail many times before you write a lot of code to support exactly your cases because there is probably no generic solution EF has no supporting methods for this scenarios. The reason is that EF has internal state machine for every entity and some associations and you must configure the state for every single entity or association you want to update, insert or delete and you must do it in compliance with EF internal rules. Setting state of the entity will change the state of that single entity but not its relations.
I do it simply by loading current entity with all relations from database and manually (in code) merging whole entity graph (simply you have detached and attached entity graph and you must transfer all changes from detached to attached one).