高级 .NET 问答 03:EF Core 查询、事务、并发与性能
041 如何准确解释顶层投影客户端计算,并指出它最容易被误解的边界?
难度: 基础
查看参考答案
结论: EF Core 可在顶层投影中对无法翻译的部分进行客户端计算,其余查询仍在服务器执行
原因: 常见误区是“所有无法翻译的表达式都会自动下载整张表再计算”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 过滤、排序等关键位置不可翻译通常会抛异常而不是静默拉取全表
最小示例: 当“Select 中调用本地格式化方法”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
042 生产环境出现“过滤写在 AsEnumerable 后导致传输量激增”时,应如何围绕查询边界组织排查?
难度: 基础
查看参考答案
结论: AsEnumerable 或物化操作会把后续运算移到客户端,应明确评估数据量和执行位置
原因: 常见误区是“调用 AsEnumerable 只改变静态类型而不改变后续执行位置”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 切换客户端前仍在查询表达式中的操作可继续由数据库执行
最小示例: 当“过滤写在 AsEnumerable 后导致传输量激增”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
043 为什么不能把“跟踪查询每次遇到同一键都会创建新对象”当成跟踪查询的最终结论?
难度: 基础
查看参考答案
结论: 跟踪查询把实体纳入 ChangeTracker,并对同一键执行身份解析以复用实例
原因: 常见误区是“跟踪查询每次遇到同一键都会创建新对象”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 长生命周期上下文会积累状态,常规请求应保持清晰工作单元边界
最小示例: 当“查询结果与已跟踪实体值不一致”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
044 上线评审涉及无跟踪身份解析时,至少应确认哪些契约和证据?
难度: 基础
查看参考答案
结论: AsNoTrackingWithIdentityResolution 在结果物化期间执行身份解析,但不会把实体留在上下文跟踪器中
原因: 常见误区是“该模式与普通跟踪查询具有完全相同的更新行为”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 临时跟踪器只服务当前枚举,不能用于后续 SaveChanges
最小示例: 当“重复关联实体需要共享实例但保持只读”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
045 如何准确解释ChangeTracker.Clear,并指出它最容易被误解的边界?
难度: 基础
查看参考答案
结论: ChangeTracker.Clear 可一次停止跟踪当前实体,通常比逐个 Detach 更高效
原因: 常见误区是“定期 Clear 可以让同一个 DbContext 安全跨所有请求共享”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 清理状态不替代正确的 DbContext 生命周期和事务边界
最小示例: 当“批处理循环中跟踪实体持续增长”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
046 生产环境出现“少量实体却传输大量结果行”时,应如何围绕笛卡尔膨胀组织排查?
难度: 基础
查看参考答案
结论: 同级集合 JOIN 可能产生行数乘积并重复主体列,造成传输和物化开销
原因: 常见误区是“数据库会自动消除 Include 产生的所有重复行”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 嵌套 ThenInclude 与同级集合的结果形状不同,应检查生成 SQL
最小示例: 当“少量实体却传输大量结果行”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
047 为什么不能把“Select 到 DTO 会让所有导航属性自动延迟加载”当成投影的最终结论?
难度: 进阶
查看参考答案
结论: 只投影接口需要的列和形状通常比加载完整实体图更节省传输、跟踪与物化成本
原因: 常见误区是“Select 到 DTO 会让所有导航属性自动延迟加载”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 投影中仍需避免 N+1 和不可翻译表达式
最小示例: 当“列表页只需三列却加载大字段”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
048 上线评审涉及DbContext 池时,至少应确认哪些契约和证据?
难度: 进阶
查看参考答案
结论: DbContext 池复用已重置的上下文实例,减少频繁构造和内部服务初始化成本
原因: 常见误区是“池化上下文会为每次请求重新执行完整构造与 OnConfiguring”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: OnConfiguring 通常只在首次创建实例时执行,请求级状态必须显式重置和注入
最小示例: 当“多租户筛选器沿用上个请求值”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
049 如何准确解释池化状态泄漏,并指出它最容易被误解的边界?
难度: 进阶
查看参考答案
结论: 池化上下文返回池前由 EF 重置内部状态,但应用自行维护的可变字段需要负责清理
原因: 常见误区是“EF 会自动重置上下文关联的任意第三方对象状态”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 手工打开连接或改变底层驱动状态也必须在归还前恢复
最小示例: 当“下一个请求读取到前一个租户信息”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
050 生产环境出现“高峰期上下文构造次数上升”时,应如何围绕池容量组织排查?
难度: 进阶
查看参考答案
结论: 池达到容量后仍可创建非池化实例完成请求,归还时超出容量的实例会被释放
原因: 常见误区是“DbContext 池容量等于数据库最大连接数并会拒绝额外请求”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 容量是复用上限而不是并发请求硬限制
最小示例: 当“高峰期上下文构造次数上升”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
051 为什么不能把“所有 EF Core 查询都必须显式编译才能进入生产”当成显式编译查询的最终结论?
难度: 进阶
查看参考答案
结论: EF.CompileQuery 和 CompileAsyncQuery 可绕过部分重复查询编译查找开销
原因: 常见误区是“所有 EF Core 查询都必须显式编译才能进入生产”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 收益主要在极高频稳定查询,模型和参数形状存在限制且必须基准验证
最小示例: 当“热点小查询 CPU 占用可见”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
052 上线评审涉及ExecuteDelete时,至少应确认哪些契约和证据?
难度: 进阶
查看参考答案
结论: ExecuteDelete 直接删除匹配行并立即执行,不需要先查询实体或调用 SaveChanges
原因: 常见误区是“ExecuteDelete 只是把实体标记 Deleted 并等待 SaveChanges”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 级联、触发器、全局过滤器和事务仍按数据库与模型配置生效
最小示例: 当“后台清理需要删除大量过期行”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
053 如何准确解释默认事务,并指出它最容易被误解的边界?
难度: 进阶
查看参考答案
结论: 关系数据库提供程序通常让一次 SaveChanges 中的变更在事务内提交
原因: 常见误区是“调用一次 SaveChanges 可以原子覆盖后续所有业务步骤”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 跨多次 SaveChanges 或外部操作需要显式事务与一致性设计
最小示例: 当“第二次保存失败留下前一次结果”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
054 生产环境出现“网络短暂中断导致命令失败”时,应如何围绕执行策略重试组织排查?
难度: 进阶
查看参考答案
结论: 执行策略可针对识别出的瞬时故障重试数据库操作
原因: 常见误区是“开启重试后任何数据库错误和业务异常都会无限重试”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 重试单元必须可重放,外部副作用和显式事务要通过策略委托统一执行
最小示例: 当“网络短暂中断导致命令失败”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
055 为什么不能把“TransactionScope 或相同数据库会自动合并所有上下文状态”当成跨上下文事务的最终结论?
难度: 实战
查看参考答案
结论: 多个 DbContext 共享事务需要共享 DbConnection 并显式使用同一 DbTransaction
原因: 常见误区是“TransactionScope 或相同数据库会自动合并所有上下文状态”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 仅使用相同连接字符串不会让两个上下文自动处于同一事务
最小示例: 当“两个上下文更新需要原子提交”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
056 上线评审涉及rowversion时,至少应确认哪些契约和证据?
难度: 实战
查看参考答案
结论: SQL Server rowversion 可作为数据库生成的并发令牌,在行更新时自动变化
原因: 常见误区是“rowversion 保存最后修改时间且可以人工按时间排序”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 它是数据库特定机制,不表示日期时间,也不能跨提供程序照搬
最小示例: 当“API 使用字节令牌检测旧版本”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
057 如何准确解释冲突值集合,并指出它最容易被误解的边界?
难度: 实战
查看参考答案
结论: 处理 DbUpdateConcurrencyException 时可比较当前值、原始值和数据库值,再决定合并策略
原因: 常见误区是“捕获异常后直接再次 SaveChanges 就会自动合并所有字段”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 刷新原始值后重试前还要重新验证业务规则和用户授权
最小示例: 当“后台作业覆盖用户刚提交的数据”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
058 生产环境出现“审计逻辑导致数据库调用变慢”时,应如何围绕命令拦截器组织排查?
难度: 实战
查看参考答案
结论: DbCommandInterceptor 可观察或修改命令执行过程,适合审计、诊断和受控策略
原因: 常见误区是“命令拦截器只在开发环境运行且不会影响延迟”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 拦截器位于所有匹配命令路径上,必须快速、线程安全并避免递归执行
最小示例: 当“审计逻辑导致数据库调用变慢”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
059 为什么不能把“启用敏感数据日志是排查生产问题的默认安全做法”当成诊断日志的最终结论?
难度: 实战
查看参考答案
结论: EF Core 日志和 DiagnosticSource 事件可揭示命令、连接、编译、跟踪与保存行为
原因: 常见误区是“启用敏感数据日志是排查生产问题的默认安全做法”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 生产环境应控制级别、采样和敏感数据,避免高开销与信息泄露
最小示例: 当“日志中意外出现用户参数”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。
060 上线评审涉及展开收缩迁移时,至少应确认哪些契约和证据?
难度: 实战
查看参考答案
结论: 兼容性要求较高的发布可先扩展数据库结构,再逐步切换读写,最后收缩旧结构
原因: 常见误区是“一次发布同时重命名列和删除旧列不会影响滚动升级”,它把一次现象、局部实现或有限条件扩大成普遍保证;正确判断必须回到平台契约并收集运行证据。
边界: 多个应用版本并存期间必须保持前后兼容并监控数据回填
最小示例: 当“滚动发布期间新旧版本交错运行”出现时,先记录配置、指标与调用路径,再验证主规则,不以单次成功、重启恢复或盲目扩容代替根因分析。