I'm using a generic service for CRUD operations. When I try to update an entity, I get the following error :
The property 'TestClass.Id' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal.
Here is the code of the service :
public virtual async Task<TDto> Update(IdType id, TRequest request)
{
var repo = dbModel.Set<T>();
var entity = await repo.Single(e => e.Id.Equals(id));
entity = _mapper.Map(request, entity);
repo.Update(entity);
await dbModel.SavesChanges();
var ret = _mapper.Map<TDto>(entity);
return ret;
}
The entity comes from the repo, so all of its properties are fulfilled from the database, and it should be tracked by EF. Then I map the updated properties from the request with AutoMapper. For example I am using these classes to test my code :
public class TestClass
{
public int Id { get; set; }
public DateTime CreationDate { get; set; }
public string Comment { get; set; }
}
public class TestClassRequest
{
public string Comment { get; set; }
}
The "entity" var is fulfilled with all the properties of the TestClass, then with the mapper only the Comment property is updated. Everything works great.
But when I try to save the changes to the database I have the error I stated before.
I assume that the repo.Update() tries to update all the properties, even the id, as stated in this explication from learnentityframeworkcore.com :
This method results in the entity being tracked by the context as Modified. The context doesn't have any way of identifying which property values have been changed, and will generate SQL to update all properties
So I added the line dbModel.ChangeTracker.DetectChanges(); before calling the SavesChanges() but I still get the same error.
Is there a way to update only modified properties with the dbModel.DbSet<T> ?