当前位置: 首页 > news >正文

C# 中 Entity Framework (EF) 和 EF Core 里的 `AsNoTracking` 方法

C# 中 Entity Framework (EF) 和 EF Core 里的 AsNoTracking 方法。是一个非常重要且能显著提升性能的特性。

核心概念:什么是变更追踪?

要理解 AsNoTracking,首先必须明白 EF 的变更追踪 机制。

当您从数据库中查询一个实体(例如,一个 Blog 对象)时,默认情况下,EF 的 DbContext 会记住它。

  • 它做了什么? DbContext 会创建这个实体的一个“快照”,并持续关注你后续对它的任何修改(比如 blog.Name = "New Name")。
  • 为什么这么做? 这是为了在你调用 SaveChanges() 时,DbContext 能自动知道哪些实体被修改了,以及具体修改了什么,从而生成正确的 UPDATE SQL 语句并执行。

简单比喻: 想象一下你的 DbContext 是一个图书馆管理员

  • 默认情况(有追踪): 你借走一本书(查询一个实体),管理员会在借阅本上记下你的名字和书号。你还书时(SaveChanges),管理员会检查书有没有破损(修改),如果有,会让你赔偿(生成 UPDATE 语句)。
  • 使用 AsNoTracking(无追踪): 你只是在图书馆里阅览这本书,没有办理借阅手续。管理员根本不知道你看过这本书。你看完后直接放回书架,管理员不会做任何检查。

什么是 AsNoTracking

AsNoTracking 是 LINQ 查询的一个扩展方法,它告诉 DbContext:“我只想读取数据,不会更新它,所以你不用费心去跟踪它的状态。”

关键特性与优势:
  1. 性能提升:这是最主要的好处。由于 DbContext 不需要创建对象的快照、维护追踪关系图,查询速度会更快,内存消耗会更少。对于复杂的只读查询,性能提升非常明显。
  2. 无状态管理:查询到的实体处于 Detached 状态。DbContext 完全忽略它们的存在。
  3. 手动更新:如果你真的需要更新一个通过 AsNoTracking 查询到的实体,你必须显式地告诉 DbContext 它的状态是 Modified,然后才能调用 SaveChanges()

举例说明

让我们通过一个简单的代码示例来对比使用和不使用 AsNoTracking 的区别。

场景定义

假设我们有一个 Blog 模型和一个 AppDbContext

public class Blog
{public int BlogId { get; set; }public string Name { get; set; }public string Url { get; set; }
}public class AppDbContext : DbContext
{public DbSet<Blog> Blogs { get; set; }
}
示例 1:默认行为(有追踪)
using (var context = new AppDbContext())
{// 默认查询:变更追踪是开启的var blog = context.Blogs.FirstOrDefault(b => b.BlogId == 1);// 此时,blog 被 DbContext 追踪// 它的状态是 EntityState.Unchanged// 我们修改实体的属性blog.Name = "全新的博客名称";// 此时,blog 的状态自动变为 EntityState.Modified// 调用 SaveChanges,EF 会检测到变化并生成 UPDATE 语句context.SaveChanges(); // 成功更新数据库
}

执行结果: 数据库中的 BlogId 为 1 的记录,其 Name 字段被更新为 “全新的博客名称”。

示例 2:使用 AsNoTracking(无追踪)
using (var context = new AppDbContext())
{// 使用 AsNoTracking 查询var blog = context.Blogs.AsNoTracking() // 关键在这里!.FirstOrDefault(b => b.BlogId == 1);// 此时,blog 不被 DbContext 追踪// 它的状态是 EntityState.Detached// 我们修改实体的属性blog.Name = "这个修改不会被保存";// 由于 DbContext 从未追踪它,所以它不知道这个对象的存在和变化// 调用 SaveChanges,EF 不会为这个 blog 做任何事情context.SaveChanges(); // 没有任何 UPDATE 语句生成
}

执行结果: 数据库中的数据没有任何变化

示例 3:如何更新一个 AsNoTracking 查询到的实体

如果你确实需要更新一个无追踪的实体,你必须手动将其附加到 DbContext 并设置其状态。

using (var context = new AppDbContext())
{// 1. 以无追踪方式查询实体var blog = context.Blogs.AsNoTracking().FirstOrDefault(b => b.BlogId == 1);// 2. 修改它blog.Name = "现在这个修改可以被保存了";// 3. 手动将实体附加到 DbContext,并标记为 Modifiedcontext.Entry(blog).State = EntityState.Modified;// 或者使用 Attach 并手动标记属性为已修改 (EF Core)// context.Attach(blog);// context.Entry(blog).Property(b => b.Name).IsModified = true;// 4. 现在调用 SaveChanges 会生成 UPDATE 语句context.SaveChanges();
}

执行结果: 数据库成功被更新。这种方式在你从 MVC/Web API 的请求中接收到一个分离的实体,并需要在数据层更新它时非常常见。


最佳实践与使用场景

  • 只读操作:如果你的查询目的仅仅是展示数据(例如,在网页上显示产品列表、报告生成等),总是使用 AsNoTracking。这是最重要的性能优化手段之一。
  • 需要更新时:如果你的意图是查询并立即修改,则不应使用 AsNoTracking,使用默认的追踪行为更方便。
  • 在 DbContext 级别禁用追踪:如果你有一个专门用于只读操作的 DbContext,你可以在配置它时全局关闭追踪。
    // 在 DbContext 的 OnConfiguring 方法中 (EF Core)
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
    }
    
    如果只是某个特定查询需要追踪,可以使用 .AsTracking()

总结

特性默认查询 (有追踪)使用 AsNoTracking
性能较慢,占用更多内存更快,占用更少内存
内存开销较高(需要快照)较低
实体状态被追踪 (Unchanged, Modified 等)分离的 (Detached)
自动更新支持不支持
适用场景需要增删改的操作只读、显示数据的操作

希望这个详细的解释和示例能帮助你彻底理解 AsNoTracking。在合适的场景下使用它,能让你的应用程序性能得到立竿见影的提升!

http://www.dtcms.com/a/569288.html

相关文章:

  • 基于视觉分析的加油站通话行为安全预警系统 构建加油安全新防线 通话行为模式识别 边缘计算通话动作监测设备
  • Traefik vs Spring Cloud:微服务架构的两种截然不同的技术路线
  • 郑州百度seo网站优广州网站开发外包哪家好
  • 高端网站建设推来客网络做seo推广公司
  • 数据挖掘6-AI总结
  • 网站首页域名如何设置访问快宿迁沭阳网站建设
  • 数据结构 —— 栈
  • 微信小程序开发案例 | 个人相册小程序(下)
  • 网站域名账号网址申请注册
  • 电商 API 数据交互最佳实践:JSON 格式优化、数据校验与异常处理
  • 重庆网站建设 沛宣织梦cms 官方网站
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十七)ELK日志分析模块--Elasticsearch介绍与配置
  • 如何使用elasticdump进行elasticsearch数据还原
  • 【运维记录】Centos 7 基础命令缺失
  • 手写 RPC 框架
  • etcd 高可用分布式键值存储
  • 【ETCD】ETCD单节点二进制部署(TLS)
  • 小网站 收入请简述网站制作流程
  • 抗辐照MCU芯片在无人叉车领域的性能评估与选型建议
  • 什么是LLM?
  • Java/PHP源码解析:一站式上门维修服务系统的全栈实现
  • MPU6050 DMP 移植中 mpu_run_self_test () 自检失败的原因与解决方法
  • 系统端实现看门狗功能
  • 算法--二分查找(二)
  • 没有网站备案可以做诚信认证嘛商城网站大概多少钱
  • 保定市场产品投放策略分析
  • Linux网络——连接、TCP全连接队列TCPdump抓包
  • Firefox 浏览器:引领网络浏览新时代
  • 【个人成长笔记】解决在Linux/Windows系统中 git pull 之后提示有未提交的更改错误信息(亲测有效)
  • 分布式训练一站式入门:DP,DDP,DeepSpeed Zero Stage1/2/3(数据并行篇)