内容纲要

1,什么叫跟踪查询

EF Core 查询中默认是跟踪查询。 意思是,当你使用 EFCore 查询数据库后,可以获取实体(查询后的数据以实体/模型对象形式返回),如果在此期间修改这些对象,那么,最后使用 SaveChanges() ,可以保存你的修改到数据库,即 持久化到数据库中 。

var blog = context.Blogs.FirstOrDefault(b => b.BlogId == 1);
blog.Rating = 5;
context.SaveChanges();

上面是很简单的示例,从数据库中查询数据,然后修改某些数据,再保存到数据库。

EF Core 不会跟踪结果中包含的无键的实体实例。 但 EF Core 会根据上述规则跟踪带有键的实体类型的所有其他实例。

如果一个表中没有设置任何主键外键,那么这个跟踪查询不会起效,使用 context.SaveChanges(); 会报错。

2,跟踪原理

每个上下文实例都有一个 ChangeTracker,它负责跟踪需要写入数据库的更改。 更改实体类的实例时,这些更改会记录在 ChangeTracker 中,然后在调用 SaveChanges 时被写入数据库。 此数据库提供程序负责将更改转换为特定于数据库的操作(例如,关系数据库的 INSERT、UPDATE 和 DELETE 命令)。

3,非跟踪查询

很多时候,我们只要求查询数据,而不会修改数据。为了可以更快速地执行任务,就使用非跟踪查询。非跟踪查询能够提高查询速度的原因是无需设置更改跟踪信息

适用场景:如果不需要更新从数据库中检索到的实体(即数据),则应使用非跟踪查询。

在查询是,使用 .AsNoTracking() 设置为 非跟踪查询

var blogs = context.Blogs
    .AsNoTracking()
    .ToList();

如果要对上下文的操作都设置非跟踪查询

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

var blogs = context.Blogs.ToList();

EF Core 在非跟踪查询中执行标识解析。

它使用了弱引用来跟踪已返回的实体。 因此,如果结果集多次包含相同的实体,则每次会返回相同的实例。 尽管具有相同标识的上一个结果超出了范围并进行了垃圾回收,EF Core 也会返回新实例。