关于 query-pipeline
用于 Entity Framework Core 查询管线开发的技能,提供查询翻译、优化、拆分查询行为及提供程序级回归测试方面的指导。
主要功能
- 01查询回归测试组织
- 02翻译回退保护
- 03保持 SQL 与 LINQ 语义
- 04拆分查询缓冲与一致性
- 05SQL 与表达式诊断
适用场景
- 01添加由提供程序覆盖的查询回归测试
- 02审查查询改写的正确性
- 03测试拆分查询终止与一致性行为
- 04检查生成的 SQL 和表达式树
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dotnet/ efcore --skill query-pipeline安装后在 Claude Code 中输入/query-pipeline确认已加载。
详细介绍
查询管道
回归测试归属
- 按内聚的查询或模型特征对查询规范测试分组。不要仅仅因为测试使用自定义模型就创建通用分类;应使用现有的特征专属层级,例如自有实体查询。
- 放置回归测试前,先检查规范测试基类和各提供程序的重写。将 LINQ 查询、模型设置和结果断言放在共享的虚拟测试中;提供程序重写应调用基类,并且只添加提供程序专属基线或已知限制。
- 仅针对某个提供程序的测试可能导致其他所有提供程序都未覆盖,即使其 SQL 断言正确也是如此。保留重写保护条件,但不要添加会迫使无关提供程序进行冗余重写的保护条件。
- 对于优化,应使用精确的结果断言,在同步和异步测试中同时覆盖符合条件和不符合条件的形态。提供具体的提供程序重写和 SQL 基线或已知限制;仅有抽象测试基类或表达式形态检查并不能证明执行覆盖率。
转换
- 转换回退必须区分已知不支持的形态和意外缺陷。不要将任意异常转化为成功回退。
- 检查失败的重写是否修改了回退将要复用的状态。对于测试协调,应先确定实际的集合、程序集和异步流边界,再判断共享静态状态是否可能发生竞争;理论测试行并非天然并行,而在
finally中重置也不具备互斥效果。
优化
- 根据重写所需的等价性进行匹配,不要盲目依赖表达式相等性。
- 保留特定上下文中的 null 语义。SQL UNKNOWN 在谓词中可以像
false一样被筛除,但在投影值中或否定运算下则不行;UseRelationalNulls、包含 null 的IN/NOT IN,以及标量与复合 LINQ 联接键,都需要不同的补偿方式。 - 保留基数和运算符顺序,而不只是匹配行。将谓词移过外联接、在
Distinct/GroupBy中添加键,或将相关 APPLY 转换为 JOIN,都可能改变结果;每个父项的分页必须保留分区和排序,剩余的外部引用必须阻止去相关化。 - 仅当重复子查询的求值方式和行选择方式等价时才共享它们。易变表达式、在后续导航扩展期间引入的查询筛选器,以及必需导航联接,都可能改变求值次数或限制操作后保留的行。复用前应检查确定性和行保留情况,并在各自的 lambda 作用域内收集候选项。
- 分别保留 SQL 类型语义和 CLR 结果语义。仅当强制转换对存储类型的影响是多余的时才移除它;对常量的强制转换可能用于确定必要的 SQL 类型。SQL 可空列本身并不能决定整形器的 nullability:对非可空标量使用
DefaultIfEmpty时,可能需要COALESCE转换为其 CLR 默认值。 - 更改查询形态时,重新映射相关状态。子查询下推或联接替换必须更新作用域内的列引用、谓词、排序、投影绑定和整形器;当多重性或 null 扩展发生变化时,应保留或重新计算标识符及其比较器。
- 证明剪枝安全性时,不能只看最终投影。未使用的联接仍可能筛选或增加行数,因此要遵守明确的可剪枝标记以及其他子句中的引用。未引用的列仍可能决定 distinct/集合运算的成员关系,或标量子查询的结果;应保留这些约定,并确保集合运算的投影兼容。
分割查询
- 修改
SplitQueryResultCoordinator时,请同时检查SplitQueryingEnumerable和GroupBySplitQueryingEnumerable,包括它们的同步和异步路径。流结束验证应在外层流真正耗尽时进行,而不是在分组边界或提前释放时进行。 - 分组读取器在生成最后一个分组的过程中可能到达物理 EOF,但该分组仍须返回。应分别测试这次成功的移动和随后到达终止状态的移动,包括验证失败和重复调用终止移动;清理操作必须保留原始异常。
- 评估内存使用时,既要考虑内部缓冲,也要考虑调用方的物化。当提供程序无法同时保持多个读取器处于活动状态时,可能需要缓冲较早的分割查询结果集;重试执行策略也可能要求缓冲。
- 缓冲无法让不同查询命令获得一致的数据库快照。命令之间发生的并发写入可能导致结果图不一致;需要保证一致性时,可考虑快照或可序列化事务,同时权衡提供程序支持情况和事务开销。
- 使用写入方事务,并在读取之间设置显式屏障,来验证跨命令一致性;不要使用休眠或仅用文字描述场景。断言根节点与子节点的值组合,而不只是键匹配;注明测试的隔离级别和重试策略适用范围。
验证
ToQueryString()显示生成的 SQL,但不会执行查询ExpressionPrinter可在管道的任意阶段转储表达式树- 通过提供程序功能测试中的
AssertSql()验证 SQL 基线,并确认生成的 SQL 与基类方法中的 LINQ 查询对应
评论
支持 Markdown