What is the best way to perform partial updates in EF core and never update certain properties?
Starting with EF Core 2.0, you can use IProperty.AfterSaveBehavior
property:
Gets a value indicating whether or not this property can be modified after the entity is saved to the database.
If Throw, then an exception will be thrown if a new value is assigned to this property after the entity exists in the database.
If Ignore, then any modification to the property value of an entity that already exists in the database will be ignored.
What you need is the Ignore
option. At the time of writing there is no dedicated fluent API method for that, but Setting an explicit value during update contains an example how you can do that.
Taking your example, something like this:
modelBuilder.Entity<MyObject>(builder =>
{
builder.Property(e => e.Prop7).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(e => e.Prop8).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
builder.Property(e => e.Prop9).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
});
Now both
public void UpdateObj(MyObject objToUpdate)
{
var myObj = _db.MyObject.First(x => x.Id == objToUpdate.Id);
_db.Entry(myObj).CurrentValues.SetValues(myObjToUpdate);
_db.SaveChanges();
}
and
public void UpdateObj(MyObject objToUpdate)
{
_db.Update(myObjToUpdate);
_db.SaveChanges();
}
will ignore Prop7
, Prop8
and Prop9
values of the passed myObjToUpdate
.
Update (EF Core 3.0+) The aforementioned property has been replaced with GetAfterSaveBehavior and SetAfterSaveBehavior extension methods.
If you have an entity:
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
And you run:
var p = ctx.Person.First();
p.Name = "name updated";
ctx.SaveChanges();
EF will generate the following SQL statement:
You can verify it using SQL Server Profiler, the same is true if you update 6/10 properties.