为何在EF Core中不能始终使用AsNoTracking?
虽然用AsNoTracking获取的实体在调用SaveChanges()时会被EF Core临时追踪,但这并不代表它能完全替代常规的追踪查询,核心原因如下:
并发冲突处理困难:追踪查询会自动记录实体的原始状态,当发生乐观并发冲突(比如多个请求同时修改同一数据)时,EF能自动对比原始值和当前值,抛出
DbUpdateConcurrencyException提醒开发者处理。但AsNoTracking不会保存原始状态,你得手动管理原始值(比如额外存储RowVersion)才能检测冲突,大幅增加了代码复杂度。关联实体的状态管理繁琐:如果实体包含导航属性(比如
Order关联OrderItem),用AsNoTracking获取的实体及其关联对象都不会被追踪。当你需要更新主实体同时同步更新关联实体时,必须手动将每个关联实体附加到上下文,还要手动设置它们的状态(Added/Modified/Deleted),很容易遗漏或设置错误。而追踪查询下,EF会自动管理所有关联实体的状态,减少出错概率。重复查询的性能损耗:追踪查询会把实体缓存到上下文的一级缓存中,后续针对同一主键的查询会直接从缓存返回,无需再访问数据库。但
AsNoTracking每次查询都会直接触发数据库请求,哪怕刚查询过同一个实体,在高频查询场景下会显著增加数据库压力。批量操作的额外开销:在批量更新场景中,使用
AsNoTracking意味着每次更新都要让EF重新初始化实体的追踪状态,相比直接修改已追踪实体,多了状态附加和原始值加载的步骤,积累起来会产生可观的性能开销。复杂业务流程的代码冗余:如果一个业务流程中需要多次修改同一实体的不同属性,用
AsNoTracking的话每次修改都要确保实体被正确附加到上下文,代码会变得冗余且容易出错。而追踪查询下,实体始终被上下文追踪,修改后直接调用SaveChanges()即可,代码更简洁直观。
内容的提问来源于stack exchange,提问作者Kaveh Kardel

