EF Core 8 (EF8) Contains报错:Microsoft.Data.SqlClient.SqlException (0x80131904): 关键字 'WITH' 附近有语法错误。
最近将原来.NET6的项目升级到.NET8,用的EF Core版本也相应升级到EF8版本,在查询数据的时候使用Contains运算符的地方报错了。
Microsoft.Data.SqlClient.SqlException (0x80131904): 关键字 'WITH' 附近有语法错误。
关键字 'with' 附近有语法错误。如果此语句是公用表表达式、xmlnamespaces 子句或者更改跟踪上下文子句,那么前一个语句必须以分号结尾。
at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__211_0(Task`1 result)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
引发的异常:“Microsoft.Data.SqlClient.SqlException”(位于 System.Private.CoreLib.dll 中)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request.
代码是这样的:
var tagList = tags.Split(',');
var currTags = await _context.Tags.Where(x => tagList.Contains(x.Text)).ToListAsync();
原来运行都没问题,使用.NET8之后就报错了。看了一下输出的SQL语句是这样的:
SELECT [t].[Id], [t].[CreatedAt], [t].[LastModifiedAt], [t].[Text]
FROM [Tags] AS [t]
WHERE [t].[Text] IN (
SELECT [t0].[value]
FROM OPENJSON(@__tagList_0) WITH ([value] nvarchar(50) '$') AS [t0]
)
我使用的数据库是SQL Server2014,怀疑是.NET8版本不支持了。在微软官方文档找到了原因。原文:https://learn.microsoft.com/zh-cn/ef/core/what-is-new/ef-core-8.0/breaking-changes#contains-in-linq-queries-may-stop-working-on-older-sql-server-versions
影响较大的更改,LINQ 查询中的 Contains 可能会在较旧的 SQL Server 版本上停止工作。
因为 .net 8 优化了 Contains 子句的 SQL 翻译,之前的 IN 查询有性能问题,但这个优化只有 SQL Server 2016 及以上版本的数据库支持,否则就会报这个错。而且即便数据库引擎版本达到,数据库本身的兼容性设置如果低于 SQL Server 2016 的话,也会报错。
解决方法:
1. 使用SQL Server 2016 (13.x) 或更高版本。如果数据库是 SQL Server 2016 (13.x) 或更高版本,或者使用的是 Azure SQL,请通过以下命令检查已配置的数据库兼容性级别:
SELECT name, compatibility_level FROM sys.databases;
2. 如果数据库版本确实低于 SQL Server 2016,或者设置为由于某种原因而无法更改的旧兼容级别,请将 EF Core 配置为还原到较旧且效率较低的 SQL,如下所示:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"<CONNECTION STRING>", o => o.UseCompatibilityLevel(120));
更新于:4个月前相关文章
- ASP.NET Core 中常用的内置中间件
- SQL Server EF使用Sequence全局自增ID
- 鸿蒙OpenHarmony系统可以运行跨平台的.NET Core吗?
- ASP.NET Core使用partial标签报错
- Asp.Net Core进程内托管 和 进程外托管的区别
- ASP.NET Core实现多语言本地化Web应用程序
- PDFiumCore | .NET Core PDF 处理渲染库
- ASP.NET Core 2.1中的ActionResult<T>
- .NET Core 3.0创建一个单独的可执行文件
- 在ASP.NET Core 2.1中使用HttpClientFactory的3种方法
- .NET Core MVC应用程序创建教程
- .NET Core中的File和PhysicalFile
- .NET Core 读取配置文件方法
- .NET Core 管道模型中间件及管道模拟实现
- ASP.NET Core多环境配置
- .NET Core 日志配置,NLog配置示例
- ASP.NET Core主机和应用启动流程
- .NET Core SkiaSharp替代System.Drawing的用法
- .NET Core 3.X路由中间件和终结点中间件
- IIS中.NET Core报错HTTP Error 500.31 - ANCM Failed to Find Native Dependencies