EntityFramework Core -Tracking and No-Tracking Queries

·

1 min read

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 提供程序,以了解这些优化是否会对您的性能产生影响。