Entity Framework Core中的ChangeTracker(变更追踪器)
Entity Framework Core中的DbContext在Microsoft.EntityFrameworkCore.ChangeTracking命名空间中包含ChangeTracker类,该类负责跟踪使用同一DbContext实例检索的每个实体的状态。它不打算直接在您的应用程序代码中使用,因为它可能在将来的版本中更改。但是,您可以使用一些方法进行跟踪。
一旦使用DbContext检索了所有实体,Entity Framework Core中的ChangeTracker类就会开始跟踪所有实体,直到它们超出其范围。 EF跟踪应用于所有实体及其属性的所有更改,以便它可以为基础数据源生成并执行适当的DML语句。
实体在任何时间点都具有以下状态之一,这些状态由EF Core中的枚举Microsoft.EntityFrameworkCore.EntityState表示。
- Added
- Modified
- Deleted
- Unchanged
- Detached
让我们看看如何根据对实体执行的操作自动更改EntityState:
Unchanged State(不变的状态)
首先,使用直接SQL查询或LINQ-to-Entities查询检索的所有实体都将具有“Unchanged”状态。
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()} ");
}
}
Output:
Entity: Student, State: Unchanged
Added State(新增状态)
使用Add()或Update()方法在DbContext中添加的所有没有键属性值的新实体都将标记为“Added”。
using (var context = new SchoolContext())
{
context.Add(new Student() { FirstName = "Bill", LastName = "Gates" });
DisplayStates(context.ChangeTracker.Entries());
}
Output:
Entity: Student, State: Added
Modified State(修改状态)
如果实体的任何属性的值在DbContext的范围内更改,则它将被标记为Modified状态。
using (var context = new SchoolContext())
{
var student = context.Students.First();
student.LastName = "LastName changed";
DisplayStates(context.ChangeTracker.Entries());
}
Output:
Entity: Student, State: Modified
Deleted State(删除状态)
如果实体的任何属性的值在DbContext的范围内更改,则它将被标记为Modified状态。
using (var context = new SchoolContext())
{
var student = context.Students.First();
student.LastName = "LastName changed";
DisplayStates(context.ChangeTracker.Entries());
}
Output:
Entity: Student, State: Modified
Deleted State(删除状态)
如果使用DbContext.Remove或DbSet.Remove方法从DbContext中删除了任何实体,则它将被标记为Deleted。
using (var context = new SchoolContext())
{
var student = context.Students.First();
context.Students.Remove(student);
DisplayStates(context.ChangeTracker.Entries());
}
Output:
Entity: Student, State: Deleted
Detached State(分离状态)
在当前DbContext实例范围之外创建或检索的所有实体都将处于Detached状态。它们也称为断开连接的实体,现有的DbContext实例不会对其进行跟踪。
var disconnectedEntity = new Student() { StudentId = 1, Name = "Bill" };
using (var context = new SchoolContext())
{
Console.Write(context.Entry(disconnectedEntity).State);
}
Output:
Detached
在上面的示例中,disconnectedEntity是在DbContext实例(上下文)的范围之外创建的。因此,对于上下文,它处于Detached状态。