EntityFramework Core -Tracking and No-Tracking Queries
Table of contents
intro
默认情况下,查询是可跟踪的,这意味着如果查询更改了某些实体的某些属性并保存它们,则这些修改将在数据库上重新执行。
您查询产品,更改其名称并保存更改。下次您查询此产品时,他的名字将是更新的。Great.
什么是 AsNoTracking?
AsNoTracking 方法允许查询不可跟踪,因此即使调用 SaveChanges 方法,数据库中也不会发生任何更改。
在我们前面的示例中绝对没有意义,但是如果您已经知道您的查询不会修改数据库怎么办?
原理
下面这段查询:
return
myDbContext.Products
.Where(x=>x.CategoryId == 1)
.ToList()
EF Core 将生成查询,将查询发送到将运行查询的数据库提供程序,然后将结果返回给 EF Core,后者将分析和映射数据,然后 EF Core 将添加它需要工作的跟踪字段(基本上它将为所有实体字段添加另一个字段来跟踪更改, 以及更多用于索引之类的东西),然后它会将结果传递给您的代码,而不是可以继续运行。
问题是什么?好吧,它没有,但 EF Core 添加跟踪字段的步骤是一个很大的步骤,如果它处理大量数据,可能会使用大量内存空间,如果您在发送查询时已经知道不会更新数据库,为什么要这样做?
让我们看看如果我们现在将 AsNoTracking
添加到查询中会发生什么。
查询如下:
return
myDbContext.Products
.AsNoTracking()
.Where(x=>x.CategoryId == 1)
.ToList()
与第一个查询相同,只是跳过了跟踪步骤:
代码有什么区别吗?除了在使用 SaveChanges 方法后,数据库没有发生任何变化这点外绝对没有区别。如果你本来就不会更新数据库,那完全没有任何区别。
Why caring about this?
使用 AsNoTracking
有什么好处?Performance!!
非跟踪查询的运行速度可以提高 7 或 8 倍,占用的内存减少 4 或 5 倍。如果您的查询操作了大量数据,那将是一个巨大的收获。
请注意以下两点:
首先,增益将在 .NET 部分,而数据库部分不会有增益。这是逻辑,因为我们看到,无论是否使用 AsNoTracking,发送到 SQL 数据库提供程序的查询完全相同,这是受影响的 EF Core 部分。
要知道的第二件事非常重要,那就是增益将取决于您使用的数据库提供程序。这篇文章中的数字是针对 SQL Server 和大多数 SQL 数据库提供商的准确数字,但 Nick Chapsas 已经证明,例如,如果您使用 SQLite,AsNoTracking 方法几乎没有效果。您必须检查您正在使用的 SQL 提供程序,以了解这些优化是否会对您的性能产生影响。