游乐游手机版
首页/AI教程/文章详情

EF Core 8 SQL Server Contains报错关键字WITH语法错误避坑指南

时间:2026-06-09 15:24
升级到EFCore8后,Contains()在SQLServer中因翻译为CTE时缺少前置分号而报错。原因是EFCore8改用CTE OPENJSON传递参数集合。可通过FromSqlRaw参数化查询、FindAsync或内存过滤等方案规避。

近段时间,许多开发团队在将项目迁移至 .NET 8 与 EF Core 8 之后,遇到了一个令人困惑的查询异常:原本运行正常的 Where(x => ids.Contains(x.id)) 语句突然抛出错误,日志中清晰显示:“关键字 'WITH' 附近有语法错误。如果此语句是公用表表达式,那么前一个语句必须以分号结尾。”——本文将从根本原因、修复方式到未来的最佳实践,一次性为你梳理清楚。

EF Core 8 + SQL Server:Contains() 突然报

1. 首先了解症状表现

假设你有一段非常常见的代码:

var ids = new List { 1, 2, 3, 5, 8 };
var users = await _db.sys_admin
    .Where(x => ids.Contains(x.id))
    .ToListAsync();

在 EF Core 6 或 7 中,这段代码完全正常。升级到 EF Core 8 后,同样的代码却报出:

Microsoft.Data.SqlClient.SqlException (0x80131904):
关键字 'WITH' 附近有语法错误。
如果此语句是公用表表达式、xmlnamespaces 子句或者更改跟踪上下文子句,
那么前一个语句必须以分号结尾。

关键线索聚焦在 WITH分号 以及 公用表表达式(CTE) 上,对应的 SQL Server 错误号为 156。

2. 根因分析:EF Core 8 对 Contains 的翻译机制发生了变更

这不是所谓的 Bug,而是 EF Core 8 引入的一个 有意为之的重大变更(Breaking Change)(官方文档明确标注为 High Impact)。

2.1 旧版本行为(EF Core 6/7)

EF 会将参数化列表的值直接内联为 SQL 常量

-- EF Core 7 生成的 SQL
SELECT [s].[id], [s].[username], ...
FROM [sys_admin] AS [s]
WHERE [s].[id] IN (1, 2, 3, 5, 8)

这种翻译方式简单直接,没有使用 CTE,也不会出现任何问题——除非你开始关注查询计划缓存。

2.2 新版本行为(EF Core 8)

EF Core 8 不再采用内联常量的方式,改为通过 OPENJSONCTE(公用表表达式) 来传递参数化集合。简化后的生成逻辑大致如下:

简单值列表(如 string/int 常量)→ 采用 OPENJSON 方式
复杂查询或多次 Contains → 采用 CTE(WITH ... AS)方式

针对 ids.Contains(x.id) 这类查询,EF 可能会生成类似下面的 SQL:

-- EF Core 8 可能生成的 SQL(简化版)
;WITH [t] AS (
    SELECT [v].[value] FROM OPENJSON(@__ids_0) ...
)
SELECT [s].[id], ...
FROM [sys_admin] AS [s]
WHERE [s].[id] IN (SELECT [t].[value] FROM [t])

问题的关键在于:WITH 前面必须有一个完整的语句并以分号 ; 结尾。如果当前 SQL 批处理中 EF 没有在前面补充分号,SQL Server 就会触发错误 156。

2.3 官方文档中的说明

微软在 EF Core 8 Breaking Changes 中明确记录了此条目(Tracking Issue #13617):

Contains in LINQ queries may stop working on older SQL Server versions
Impact: High

相关链接:https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-8.0/breaking-changes#contains-in-linq-queries-may-stop-working-on-older-sql-server-versions

3. 哪些场景会触发此错误?

并非所有 Contains 都会引发问题,但它可能在意想不到的时刻出现。触发条件包括但不限于:

应用场景风险等级
ids.Contains(x.id)idsList
来源:https://cloud.tencent.com.cn/developer/article/2684732
上一篇WorkBuddy一台电脑多账号切换使用心得 下一篇MCP协议核心概念及Agent Harness连接外部工具的实现方法
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
RAG四标融合企业知识资产体系四库协同GEO优化实践
AI教程 · 2026-07-01

RAG四标融合企业知识资产体系四库协同GEO优化实践

生成式AI正在彻底改写信息检索的底层逻辑。传统SEO依赖关键词堆砌和外链建设的策略,在大模型的内容采信规则下已经基本失效。取而代之的,是生成式引擎优化(GEO)。它不再关注外链数量,而是重点衡量你的知识是否结构化、证据链是否坚实、信源是否可靠——这些维度才是RAG(检索增强生成)架构真正看重的核心指

一个普通上班人分享WorkBuddy使用心得与真实体验
AI教程 · 2026-07-01

一个普通上班人分享WorkBuddy使用心得与真实体验

前言 最近我开始使用WorkBuddy——这是腾讯推出的一款AI办公工作台。差不多用了一周时间,趁印象还新鲜,把真实的使用感受记录下来,给还在犹豫的朋友做个参考。不吹不黑,只说实际体验。 初印象:不只是聊天机器人 之前用过不少AI工具,大多数就是个对话框,你问它答,答完就结束了。WorkBuddy不

AI幻觉变真功能实战教程:App Inventor 2视频录制拓展一周开发实录
AI教程 · 2026-07-01

AI幻觉变真功能实战教程:App Inventor 2视频录制拓展一周开发实录

先讲一个颇具戏剧性的开端。 这件事的开端颇显荒诞——有用户前来咨询,称AI Pro版的介绍中提到我们有一款“视频录制拓展”。团队全体成员都感到困惑,翻遍产品列表,发现根本不存在该组件。AI那种“一本正经胡说八道”的能力,这次确实让我们陷入尴尬。 按常理,此事到此便可结束——一句“抱歉,暂时没有这个拓

别再混淆OLAP和SQL-on-Hadoop两者查询本质不同
AI教程 · 2026-07-01

别再混淆OLAP和SQL-on-Hadoop两者查询本质不同

OLAP和SQL-on-Hadoop虽都使用SQL查询数据,但本质不同。SQL-on-Hadoop负责海量数据批量计算与ETL,查询速度秒级至分钟级;OLAP通过预聚合实现毫秒级多维分析,适合BI报表。两者在数据平台分工协作,前者是后厨加工,后者是前台快速服务。

GEO优化深度解析:AI偏好FAQ还是长文内容?
AI教程 · 2026-07-01

GEO优化深度解析:AI偏好FAQ还是长文内容?

在GEO优化中,AI对内容形式无统一偏好:FAQ在简单查询中引用率41%,长文在复杂查询中达58%。内容应基于用户意图选择形式,FAQ适配简单事实类问题,长文建立主题权威,两者互补而非替代。