站点图标 江湖人士

Entity Framework Core的变更跟踪(ChangeTracker)

EF Core获取上下文SQL语句

EF Core获取上下文SQL语句

Entity Framework Core中的上下文DbContext类包含了一个ChangeTracker类,处于Microsoft.EntityFrameworkCore.ChangeTracking的命名空间,其负责跟踪使用相同的检索每个实体的状态的DbContext实例。它不打算直接在您的应用程序代码中使用它,因为它可能在将来的版本中更改。但是,您可以使用某些方法进行跟踪。

EF Core中 ChangeTracker类在使用DbContext后立即开始跟踪所有实体,直到它们超出作用域。EF 跟踪应用于所有实体及其属性的所有更改,以便它可以构建和执行适当的DML语句到底层数据源。

任何时间点的实体都具有以下状态之一,由Microsoft.EntityFrameworkCore.EntityStateEF Core中的枚举表示。

让我们看看如何EntityState根据对实体执行的操作自动更改。

状态未改变(Unchanged State )

首先,使用直接SQL查询或LINQ到实体查询检索的所有实体都将具有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()} ");
    }
}

输出:Entity: Student, State: Unchanged

添加状态(Added State)

DbContext使用Add()Update()方法中添加的所有没有键属性值的新实体都将标记为已添加。

using (var context = new SchoolContext())
{              
    context.Add(new Student() { FirstName = "Bill", LastName = "Gates" });
    
    DisplayStates(context.ChangeTracker.Entries());
}

输出:Entity: Student, State: Added

修改状态(Modified State)

如果实体的任何属性的值在范围内更改DbContext,则它将被标记为已修改状态。

using (var context = new SchoolContext())
{
    var student = context.Students.First();
    student.LastName = "LastName changed";
              
    DisplayStates(context.ChangeTracker.Entries());
}

输出:Entity: Student, State: Modified

删除状态(Deleted State)

如果从DbContext使用DbContext.RemoveDbSet.Remove方法中删除任何实体,则它将被标记为已删除。

using (var context = new SchoolContext())
{
    var student = context.Students.First();
    context.Students.Remove(student);
    
    DisplayStates(context.ChangeTracker.Entries());
}

输出:Entity: Student, State: Modified

分离状态(Detached State)

从当前DbContext实例的范围中创建或检索的所有实体都将具有“已分离”状态。它们也称为无连接的实体,并且不会被现有DbContext实例跟踪。

var disconnectedEntity = new Student() { StudentId = 1, Name = "Bill" };

using (var context = new SchoolContext())
{              
    Console.Write(context.Entry(disconnectedEntity).State);
}

输出:Detached

在上面的示例中,disconnectedEntity是在DbContext实例(context)的范围之外创建的。因此,它处于Detached状态的上下文中。

退出移动版