The DbContext in Entity Framework Core includes the ChangeTracker class in Microsoft.EntityFrameworkCore.ChangeTracking
namespace which is responsible of tracking the state of each entity retrieved using the same DbContext
instance.
It is not intended to use it directly in your application code because it may change in future versions.
However, you can use some methods for tracking purpose.
The ChangeTracker
class in Entity Framework Core starts tracking of all the entities as soon as it is retrieved using DbContext
, until they go out of its scope.
EF keeps track of all the changes applied to all the entities and their properties, so that it can build and execute appropriate DML statements to the underlying data source.
An entity at any point of time has one of the following states which are represented by the enum Microsoft.EntityFrameworkCore.EntityState
in EF Core.
Let's see how the EntityState
is changed automatically based on the action performed on the entity.
First, all the entities retrieved using direct SQL query or LINQ-to-Entities queries will have the Unchanged state.
public static void Main() { using (var context = new SchoolContext()) { // retrieve entity var student = context.Students.First(); DisplayStates(context.ChangeTracker.Entries()); } } private static void DisplayStates(IEnumerable<EntityEntry> entries) { foreach (var entry in entries) { Console.WriteLine($"Entity: {entry.Entity.GetType().Name}, State: {entry.State.ToString()} "); } }
All the new entities without key property value, added in the DbContext
using the Add()
or Update()
method will be marked as Added.
using (var context = new SchoolContext()) { context.Add(new Student() { FirstName = "Bill", LastName = "Gates" }); DisplayStates(context.ChangeTracker.Entries()); }
If the value of any property of an entity is changed in the scope of the DbContext
, then it will be marked as Modified state.
using (var context = new SchoolContext()) { var student = context.Students.First(); student.LastName = "LastName changed"; DisplayStates(context.ChangeTracker.Entries()); }
If any entity is removed from the DbContext
using the DbContext.Remove
or DbSet.Remove
method, then it will be marked as Deleted.
using (var context = new SchoolContext()) { var student = context.Students.First(); context.Students.Remove(student); DisplayStates(context.ChangeTracker.Entries()); }
All the entities which were created or retrieved out of the scope of the current DbContext
instance, will have the Detached state.
They are also called disconnected entities and are not being tracked by an existing DbContext
instance.
var disconnectedEntity = new Student() { StudentId = 1, Name = "Bill" }; using (var context = new SchoolContext()) { Console.Write(context.Entry(disconnectedEntity).State); }
In the above example, disconnectedEntity
is created out of the scope of DbContext
instance (context). So, it is in the Detached state for the context.