当我们透过Entity framework 查询或异动DB的资料时,
会将资料暂存至DbContext快取中,可在后续针对同一个资料表的异动中进行资料比对,
但在部分语法仅做查询,不会异动到DB的资料时,
DbContext快取可能会存取过多非必要的资料,造成效能上的问题。
若想要让程式忽略特定的查询结果时,
可以使用AsNoTracking()方法,让该查询不被快取,
这样就能够减少资源损耗,进而提升处理效能。
範例
以下程式码仅针对DB做查询,由于没有任何异动,
故针对这个部分做追蹤其实是增加额外的资源负担:
var employee1 = context.Employees.Where(e => e.Catalog == 1).FirstOrDefault();return employee1;
在不需要追蹤的部分加入AsNoTracking()后,
对改善查询速度有很大的帮助:
var employee1 = context.Employees.AsNoTracking().Where(e => e.Catalog == 1).FirstOrDefault();return employee1;
================================================
一般在使用AsNoTracking()后异动的资料,无法透过SaveChanges()做修改,
因为SaveChanges()也是根据快取的资料去和DB资料做比对,
若资料在有异动的情况下仍想使用AsNoTracking(),
可以使用context.Entry(),变更部分资料的实体状态,
但仅适合少部分栏位需要变更,其余资料仍不追蹤时使用:
using (var context = new MyDbContext()){ var employee1 = context.Employees.AsNoTracking().Where(e => e.Catalog == 1).FirstOrDefault(); employee1.Email = "test@aa.bb.cc"; context.Entry(employee1).State = EntityState.Modified; context.SaveChanges();}
参考资料:
使用 AsNoTracking
Entity Framework .AsNoTracking() – why & how (EF and EF Core)
使用实体状态