When entities are being tracked (this is the default, to track changes) EF Core is efficient with updates in that if there are several properties for a model and only one or two properties changed the update statement only updates those columns/properties which changed rather than every column/property.
Model
public partial class Person
{
public int Id { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateOnly BirthDate { get; set; }
}
Example 1
Read data.
await using var context = new Context();
Person person = context.Person.FirstOrDefault();
Change FirstName and LastName.
person.FirstName = "Jane";
person.LastName = "Adams";
Here the LastName is marked as not modified.
context.Entry(person).Property(p => p.LastName).IsModified = false;
Save changes.
var saveChanges = await context.SaveChangesAsync();
Using a log file to see what EF Core generated for the above, note only FirstName was updated.
info: 6/13/2024 06:36:37.171 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (27ms) [Parameters=[@p1='1', @p0='Jane' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Person] SET [FirstName] = @p0
OUTPUT 1
WHERE [Id] = @p1;
Now, let's update the LastName.
person.LastName = "Cater";
saveChanges = await context.SaveChangesAsync();
Log file entry, only LastName property was updated.
info: 6/13/2024 06:36:37.188 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@p1='1', @p0='Cater' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Person] SET [LastName] = @p0
OUTPUT 1
WHERE [Id] = @p1;
Example 2
Continued from the first example. Here a super simple model is introduced, think of it as a DTO (Data Transfer Object).
public class PersonModel
{
public int Id { get; set; }
public string FirstName { get; set; }
}
Here we create a detached Person.
int identifier = 2;
person = new() { Id = identifier };
PersonModel model = new() { Id = identifier, FirstName = "Greg" };
context.Attach(person);
context.Entry(person).CurrentValues.SetValues(model);
saveChanges = await context.SaveChangesAsync();
- Create a new Person.
- Set the Id property to 2.
- Create an instance of PersonModel with properties set.
- Attach the new Person which will now be tracked by the change tracker.
- Set the new Person instance values to the properties of the PersonModel.
- Save changes.
Log file
info: 6/13/2024 06:36:37.197 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (1ms) [Parameters=[@p1='2', @p0='Greg' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [Person] SET [FirstName] = @p0
OUTPUT 1
WHERE [Id] = @p1;
What's the point?
To show that EF Core is efficient with updates which is important more so for web applications than desktop applications, less traffic, quicker response to and from a database.
Source code
Although the above samples are simple, in the source code try experimenting.
Source code notes
- Each time the project runs the database is recreated.
- Data is generated in the class MockedData.
- Data from above is assigned under Data\Context class in OnModelCreating method.