db.Entry(model).State = EntityState.Modified;
db.Entry(model).Property(x => x.Token).IsModified=false;
db.SaveChanges();
Where are the CreatedAt and CreatedBy fields getting updated in the first place? I have used the approach in the article you linked to (your #3 below) on a few projects and it's worked great for me. The AuditAttribute is in charge of setting the Created values and the Modified values, so you don't have to undo any of them, but it controls all of that for you.
Is it not possible to control the setting of those values? If that is out of your control and they get set when they shouldn't, I'm not sure that is the responsibility of the repository to fix, but if it needs to be, then I guess you could get access to the DbContext by created a base class that your repositories inherit from that give you access to that property. The downside there is that you are locking yourself into EF being the underlying data access layer.
You could also do a Get from the repository to get the original values and replace them, but that obviously is not very performant and does an extra DB call.
If you return false from OnUpdateExecuting then the update won't actually complete and so the cache will not get updated, but the database shouldn't get updated either. Returning false, essentially stops the update from happening. This is designed so that the hooks can check values and stop the Add or Update from completing, which can be useful in some cases.
Most of the time you will be returning true, because you want the Add or Update to actually happen.
Jeff Treuting
Director of Software Delivery
Fairway Technologies Inc. | Our People, Your Solution.®
(858) 454-4471 x209
(310) 428-5426
fairwaytech.com |
public override bool OnUpdateExecuting<T, TKey>(T entity, RepositoryActionContext<T, TKey> context)
{
if (db != null)
{
IAuditable auditableEntity = entity as IAuditable;
if (auditableEntity != null)
{
db.Entry(auditableEntity).State = EntityState.Modified;
db.Entry(auditableEntity).Property(x => x.CreatedAt).IsModified = false;
db.Entry(auditableEntity).Property(x => x.CreatedBy).IsModified = false;
db.SaveChanges();
return false;
}
}
return true;
}
I think I'm missing a key piece to the puzzle.
You said "My model is updated by creating an instance of my entity from my view model. When I call the update method of the repository, then all the fields are updated, this includes the CreatedAt and CreatedBy fields."
When you pass the model into the repository, are the value for CreatedAt and CreatedBy already updated to something? I'm assuming that the view model is not passing those values back in, so it feels like they should be the default values, either NULL or 1/1/0001 (I think that is the default for DateTime). So when do those get set if you aren't specifically setting them yourself? Is it updating them at the database level maybe?
The idea behind the AuditAttribute is that it will take care of managing the values of the Created and Modified fields so that you don't do it or worry about it anywhere else. No one else should be touching those values and then you can set them in the attribute based on if it is an update or insert, and then you don't have to tie into the DbContext directly at all because you are just updating properties on the model that is then going to b saved by the underlying DbContext.
Jeff Treuting
Director of Software Delivery
Fairway Technologies Inc. | Our People, Your Solution.®
(858) 454-4471 x209
(310) 428-5426
fairwaytech.com |
I see what you are saying now.
Have you tried, not calling SaveChanges() where you are and instead flag those fields as not modified and return true. Then SaveCHanges() will get called by the repository later on and the caching will happen as well.
You will need to test if the updated cached values have the proper values for the Created properties as they might not in this case, but I'm not sure off the top of my head.
Jeff Treuting
Director of Software Delivery
Fairway Technologies Inc. | Our People, Your Solution.®
(858) 454-4471 x209
(310) 428-5426
fairwaytech.com |