EF Core 实体跟踪与非跟踪查询 AsNoTracking()详解

在Entity Framework Core (EF Core) 中,实体跟踪(Entity Tracking)和非跟踪(Non-Tracking)查询是两种不同的查询方式,它们在处理数据库查询时有着不同的性能和内存使用特点。了解何时使用哪种查询方式对于优化应用程序的性能非常重要。

实体跟踪(Entity Tracking)

当你在EF Core中执行一个查询并加载实体时,默认情况下,EF Core会跟踪这些实体以便于进行更改跟踪。这意味着EF Core会将这些实体添加到它的“更改跟踪器”中,这样你就可以对这些实体进行更改,并通过SaveChanges()方法将更改保存回数据库。
例如:


var employees = dbContext.Employees.ToList();

在这个例子中,employees列表中的每个Employee实体都被EF Core跟踪,这意味着你可以修改这些实体并保存更改。
非跟踪查询(AsNoTracking)
如果你不需要对查询结果进行更改跟踪,你可以使用AsNoTracking()方法。这告诉EF Core在执行查询时不要跟踪这些实体,这样可以减少内存使用并提高查询性能。这对于只读操作非常有用,例如,当你只需要从数据库中读取数据而不做任何修改时。
例如:

var employees = dbContext.Employees.AsNoTracking().ToList();

在这个例子中,employees列表中的每个Employee实体都不会被EF Core跟踪。这意味着你不能修改这些实体并期望通过SaveChanges()保存这些更改。

使用场景

使用实体跟踪:当你需要修改或保存查询结果时。例如,在一个表单编辑页面加载数据,然后修改后提交到数据库。

使用非跟踪查询:当你只需要读取数据而不做任何修改时。例如,显示一个报告或列表页面。

注意事项

性能:非跟踪查询通常比跟踪查询更快,因为它们不需要维护更改跟踪信息。

内存使用:非跟踪查询使用的内存更少,因为EF Core不需要为每个实体维护更改跟踪信息。

更改保存:如果你尝试修改一个非跟踪实体并调用SaveChanges(),EF Core会抛出异常,因为它不知道如何处理对这些实体的更改。

示例:混合使用

有时,你可能需要在同一个查询中部分使用跟踪和部分使用非跟踪。这可以通过组合使用来实现:

var employee = dbContext.Employees.AsNoTracking().FirstOrDefault(e => e.EmployeeId == id);
if (employee != null)
{
employee.Name = "New Name"; // 这会抛出异常,因为employee是非跟踪的
}

在这种情况下,如果你需要修改employee对象,你应该首先将其转换为可跟踪的实体:

var employee = dbContext.Employees.AsNoTracking().FirstOrDefault(e => e.EmployeeId == id);
if (employee != null)
{
var trackedEmployee = dbContext.Employees.Attach(employee); // 转换为可跟踪的实体
trackedEmployee.Name = "New Name"; // 现在可以修改并保存更改了
dbContext.SaveChanges();
}

通过这种方式,你可以根据具体需求选择合适的查询方式。

来源:www.aiug.cn
声明:文章均为AI生成,请谨慎辨别信息的真伪和可靠性!