You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8.0升级后特定LINQ语句出现SQL语法错误求助

升级.NET 8.0 + EF Core 8后LINQ Contains语句SQL语法错误排查与解决

问题背景

项目从.NET Core 3.1升级至.NET 8.0,同步更新EF Core版本后,执行包含Contains的LINQ语句时触发SQL语法错误,错误提示:

Incorrect syntax near the keyword 'WITH'.
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

涉事LINQ语句:

return context.TransactionEvents 
              .Where(x => transList.Contains(x.TransactionId)
                          && x.EventId == 30);

原因分析

  1. EF Core SQL生成逻辑变更:
    EF Core 3.x处理Contains时直接生成IN子句;而EF Core 8.x针对元素数量较多的集合(默认阈值为1000),会自动生成带CTE(公共表表达式)的SQL。如果之前的数据库会话中存在未正确终止的SQL语句(缺少分号),就会触发该语法错误。

  2. 依赖冲突:
    项目同时引用了EntityFramework(EF6)和Microsoft.EntityFrameworkCore(EF Core),两个ORM框架的上下文类型可能混淆,导致生成不符合预期的SQL。此外,项目保留的旧版ASP.NET Core MVC(2.x)依赖与.NET 8兼容性不佳,间接影响EF Core的执行逻辑。

  3. 集合大小触发CTE模式:
    当transList的元素数量超过EF Core 8的默认阈值(1000)时,自动启用CTE模式,而旧版数据库驱动或会话状态可能不兼容这种语法。

解决方案

方案1:强制EF Core使用IN子句而非CTE

通过配置修改EF Core的SQL生成行为,强制对Contains使用IN子句:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer("你的数据库连接字符串", options =>
    {
        // 设置最大批量大小为1000,匹配IN子句的SQL限制
        options.MaxBatchSize(1000);
        // 强制使用单查询模式,避免自动切换到CTE
        options.UseQuerySplittingBehavior(QuerySplittingBehavior.SingleQuery);
    });
}

如果transList元素数量超过1000,可手动分批查询后合并结果:

var batchSize = 1000;
var results = new List<TransactionEvent>();

for (int i = 0; i < transList.Count; i += batchSize)
{
    var currentBatch = transList.Skip(i).Take(batchSize).ToList();
    var batchData = context.TransactionEvents
        .Where(x => currentBatch.Contains(x.TransactionId) && x.EventId == 30)
        .ToList();
    results.AddRange(batchData);
}

return results;

方案2:清理冲突依赖

移除项目中冗余、冲突的依赖包,确保依赖版本统一:

  1. 删除EntityFramework(EF6)的引用,项目使用EF Core,两者不可混用
  2. 删除旧版Microsoft.AspNetCore.Mvc.Core和Microsoft.AspNetCore.Mvc.ViewFeatures(2.x版本),改用.NET 8内置的ASP.NET Core组件
  3. 确保所有EF Core相关包版本统一为8.0.1

修改后的项目文件示例:

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
  <!-- EF Core核心依赖 -->
  <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
  <!-- 如需ASP.NET MVC功能,使用.NET 8对应包 -->
  <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="8.0.1" />
</ItemGroup>

方案3:验证DbContext继承关系

确保自定义DbContext正确继承自Microsoft.EntityFrameworkCore.DbContext,而非EF6的System.Data.Entity.DbContext,避免类型混淆导致的异常。

验证方法

修改后重新编译项目,开启EF Core日志查看生成的SQL语句,确认是否生成预期的IN子句而非CTE,再执行原LINQ语句验证是否解决错误。

内容的提问来源于stack exchange,提问作者Nikhil_TP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:05:21