Reputation: 43
I have been working with ASP.NET Core to build the API and for data access I am using EF Core. Surfing around Stackoverflow and Google, I can't find a way to update only modified columns with the repository pattern.
Is there any way to check whether values have changed or not?
public virtual void Update(T entity)
{
// DbContext.Attach(entity);
var dbEntityEntry = DbContext.Entry(entity);
foreach (var property in dbEntityEntry.Properties)
{
var original = dbEntityEntry.OriginalValues.GetValue<object>(property.Metadata.Name);
var current = dbEntityEntry.CurrentValues.GetValue<object>(property.Metadata.Name);
if (original != null && !original.Equals(current))
dbEntityEntry.Property(property.Metadata.Name).IsModified = true;
}
}
I tried to implement like EF 6 but it is throwing an InvalidCastException
System.InvalidCastException: 'Unable to cast object of type System.Func'2[Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry,System.Int32]' to type 'System.Func`2[Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry,System.Object]'.'
I am directly updating object as received from client to in action controller and updating it.
Any help would be really appreciated.
Thanks
Upvotes: 2
Views: 4321
Reputation: 5399
If the original T Entity that your passing in is not originally retrieved from the dbContext then the entity wont be tracked, so EF itself wont be able to track what properties have changed or not.
Also calling dbContext.Update marks all properties on an entity as dirty either way.
The best suggestion would be to first fetch the entity from the DBContext, then use something like automapper to map the properties of the passed in entity to your retrieved model, then call DbContext.SaveChanges() this will then only update properties that have changed during the map. Automapper will take care of only mapping properties that exist on both sides, and you can configure the mapping if you need more fine grained control.
Psuedo code below:
public virtual void Update(T entity)
{
var existingEntity = DbContext.Entity.First(x => x.Id == entity.Id);
autoMapper.Map(entity, existingEntity);
DbContext.SaveChanges();
}
Upvotes: 2