返回题库高级 .NET 刷题ASP.NET Core 问答题 · 第 5 / 5 篇

ASP.NET Core 问答 05:EF Core、部署、性能与生产故障排查

081 DbContext 为什么通常按请求注册为 Scoped?

难度: 基础

查看参考答案

结论: 它适合作为短生命周期工作单元,跟踪一次业务操作中的实体变化

原因: 长时间持有会积累跟踪状态且不支持并发操作

边界: 一个请求也可能需要多个工作单元,后台任务必须自建作用域

最小示例: AddDbContext 默认 scoped

082 为什么同一个 DbContext 不能并行查询?

难度: 基础

查看参考答案

结论: DbContext 不支持并发操作,每个异步调用应立即 await

原因: ChangeTracker、连接和内部状态不是并发会话

边界: 需要并行时创建独立 Context,并评估事务和连接压力

最小示例: 不要在同一 context 上 Task.WhenAll

083 跟踪查询与 AsNoTracking 如何选择?

难度: 基础

查看参考答案

结论: 需要修改并 SaveChanges 时使用跟踪,只读查询优先投影或无跟踪

原因: 跟踪提供身份解析和变更检测,但有内存与 CPU 成本

边界: 无跟踪仍可能返回实体对象,只是不加入当前 Context 跟踪

最小示例: 列表页使用 AsNoTracking

084 如何消除 N+1 查询?

难度: 基础

查看参考答案

结论: 用投影、Include 或批量查询一次取得需要的数据

原因: 循环中的懒加载会随行数增加数据库往返

边界: 一次巨大 Include 也可能过度加载,需按结果形状测量

最小示例: Select 直接投影订单及客户名

085 单查询与 Split Query 如何权衡?

难度: 基础

查看参考答案

结论: 单查询减少往返但可能笛卡尔膨胀,拆分查询降低重复行但增加往返和一致性边界

原因: 多个集合 Include 时数据乘积可能远大于实体数量

边界: 拆分查询期间并发修改可能让各结果集不是同一快照

最小示例: 用 AsSplitQuery 后测量 SQL 与数据量

086 为什么投影常是 EF 查询优化首选?

难度: 基础

查看参考答案

结论: Select 只取需要列和形状,减少传输、物化与跟踪

原因: 直接加载完整实体会读取无用列和导航

边界: 投影中包含实体时仍可能跟踪,应检查结果类型

最小示例: Select new OrderDto

087 如何处理乐观并发冲突?

难度: 进阶

查看参考答案

结论: 配置并发令牌,捕获 DbUpdateConcurrencyException 后按业务选择重试、合并或提示冲突

原因: 更新语句会把原令牌放入条件,受影响行数为零表示状态已变化

边界: 盲目重试可能覆盖他人修改,必须重新读取并决定

最小示例: 使用 rowversion

088 SaveChanges 是否自动使用事务?

难度: 进阶

查看参考答案

结论: 单次 SaveChanges 在支持的提供程序上通常以事务保证该批更改原子性

原因: 跨多次 SaveChanges 或外部系统需要显式事务、执行策略或补偿

边界: 数据库事务不能覆盖消息队列和 HTTP 调用

最小示例: Outbox 将消息与业务数据同库提交

089 迁移应如何进入生产?

难度: 进阶

查看参考答案

结论: 在发布流程审查并生成可回滚或幂等脚本,由受控身份执行

原因: 应用启动时所有实例同时迁移可能竞争并放大故障

边界: 大表变更要分阶段兼容旧新版本并评估锁

最小示例: 先加可空列,再回填,最后收紧约束

090 Compiled Query 何时值得使用?

难度: 进阶

查看参考答案

结论: 仅在高频、稳定形状查询且分析确认编译开销显著时使用

原因: EF 已缓存普通查询形状,数据库往返通常更昂贵

边界: 参数和模型必须符合编译委托契约,不能替代索引优化

最小示例: 用基准比较 EF.CompileAsyncQuery

091 如何发现慢 EF 查询?

难度: 进阶

查看参考答案

结论: 记录命令耗时、查看生成 SQL 和执行计划,并关联请求 trace

原因: 只看 LINQ 源码无法判断翻译结果、索引和实际基数

边界: 生产日志要避免泄露参数敏感数据

最小示例: TagWith 标记关键查询

092 容器中的 ASP.NET Core 应监听什么地址?

难度: 进阶

查看参考答案

结论: 按平台注入端口并监听容器可访问接口,而不是只绑定 localhost

原因: 容器端口映射不改变进程内部监听地址

边界: 生产通常由编排平台和反向代理提供外部入口

最小示例: ASPNETCORE_HTTP_PORTS 配置端口

093 反向代理后为什么要处理 Forwarded Headers?

难度: 进阶

查看参考答案

结论: 应用需要可信地恢复原始 scheme、host 和客户端地址

原因: 否则 HTTPS 重定向、链接生成和安全策略可能判断错误

边界: 只能信任已知代理并限制转发数量,不能接受任意客户端伪造头

最小示例: 配置 KnownProxies 或 KnownNetworks

094 滚动发布为什么需要向后兼容?

难度: 进阶

查看参考答案

结论: 新旧实例会短暂共存,数据库与消息契约必须同时被两版理解

原因: 一次性破坏字段或协议会让部分流量失败

边界: 使用扩展再收缩策略,先发布兼容读写再清理旧字段

最小示例: 消息新增可选字段

095 如何设计就绪探针?

难度: 实战

查看参考答案

结论: 检查实例接流量所需的关键本地状态,并设置快速超时

原因: 把所有远程依赖都做深度查询会放大故障并拖垮依赖

边界: 存活探针应更轻,避免依赖抖动触发重启循环

最小示例: 启动完成后 readiness 成功

096 ASP.NET Core 热路径应先优化什么?

难度: 实战

查看参考答案

结论: 先用指标和 profiler 找到 CPU、分配、锁、I/O 或数据库瓶颈

原因: 凭感觉改 Span 或缓存可能增加复杂度却不改善端到端延迟

边界: 在 Release 和代表性负载下测量,关注吞吐与尾延迟

最小示例: dotnet-counters 后再采集 trace

097 线程池饥饿有哪些常见原因?

难度: 实战

查看参考答案

结论: 请求路径阻塞异步 I/O、长同步等待或大量突发工作会耗尽工作线程

原因: 线程增长有延迟,队列会导致延迟阶梯上升

边界: 不要用 Task.Run 包装所有 I/O,应该端到端 async

最小示例: 避免 .Result 和同步网络调用

098 如何诊断内存持续增长?

难度: 实战

查看参考答案

结论: 区分泄漏、缓存增长、高分配率和 GC 暂时堆扩张,再用计数器、dump 和引用链定位

原因: 只看进程工作集不能证明托管泄漏

边界: 采集 dump 可能暂停或增加成本,要在合适环境操作

最小示例: 观察 heap size、allocation rate 与 Gen2

099 为什么重试、超时和熔断要协同设计?

难度: 实战

查看参考答案

结论: 超时限制单次等待,重试处理瞬时失败,熔断在持续故障时快速失败

原因: 策略叠加会扩大总时长和下游负载,必须共享总体截止时间并加抖动

边界: 非幂等请求不能无条件重试,熔断也不能替代容量规划

最小示例: HttpClient 弹性管道限制最大尝试次数

100 生产故障排查的第一步是什么?

难度: 实战

查看参考答案

结论: 先确认影响范围、时间线、近期变更和关键 SLI,再保全证据并止损

原因: 没有共同事实就直接重启或改配置可能销毁证据并扩大问题

边界: 紧急止损与根因分析可以并行,但变更要可回滚并记录

最小示例: 对比发布前后错误率和 P99

官方资料

当前分类

ASP.NET Core 问答题

查看全部分类 →
  1. 01ASP.NET Core 问答 01:宿主、管道、配置与依赖注入20 题
  2. 02ASP.NET Core 问答 02:Minimal API、MVC、路由、绑定与验证20 题
  3. 03ASP.NET Core 问答 03:认证、授权、安全、缓存与状态20 题
  4. 04ASP.NET Core 问答 04:后台任务、实时通信、测试与可观测性20 题
  5. 05ASP.NET Core 问答 05:EF Core、部署、性能与生产故障排查20 题
ESC

输入关键词开始搜索