.NET 8 和 SQL Server 2016 - Contains() 抛出错误

B_C*_*Cbk 5 sql-server entity-framework-core asp.net-core .net-8.0 ef-core-8.0

我决定将我的项目从 切换.NET6.NE 8. 我的项目数据库是SQL Server 2016。

起初一切都很顺利,但我遇到了一个错误:

var seferIds = tList.expedition.Select(r => r.Key).ToArray();
var sql = (from h in context.Line
           join v in context.Route on h.id equals v.lineId
           join s in context.Expedition on v.id equals s.routeId
           where seferIds.Contains(s.id)
           select new { h, v, s })
          .ToDictionary(r => r.s.id);
Run Code Online (Sandbox Code Playgroud)

这样,我就无法Contains()在使用数据库表 ( ) 创建的 Linq 查询中使用AsQueryable

我做了一些研究,如果我将其定义为

where seferIds.AsQueryable().Contains(s.id)
Run Code Online (Sandbox Code Playgroud)

错误消失。同时,我需要seferIds.Any()在我的代码中以 的形式进行空检查。

我查看了使用 SQL Server 2019 作为数据库是否会遇到相同的错误,并且可以where seferIds.Contains(s.id)正常工作,没有任何问题,也没有错误。

至于我的问题,这个问题是.net8不再兼容旧数据库版本的问题吗?还有其他我错过的情况吗?

我想知道这个错误是否有不同的解决方案。

Moh*_*deh 7

在将项目更新到较新版本之前,请务必阅读“重大更改”,您的问题也在此列表中:

EF Core 8 (EF8) 中的重大更改

新的EF Core 8.0转换使用 SQL ServerOPENJSON函数将值作为 JSON 数组传输。这解决了先前技术固有的性能问题;但是,该OPENJSON功能在 SQL Server 2014 及以下版本中不可用。

解决方案:

OPENJSON函数是在 SQL Server 2016 (13.x) 中引入的;为此,只需UseCompatibilityLevel在配置上下文选项时调用新方法即可。 120 参数是所需的 SQL Server 兼容性级别;120 对应于 SQL Server 2014 (12.x)。完成此操作后,EF 将生成先前的翻译。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlServer(@"<CONNECTION STRING>", o => o.UseCompatibilityLevel(120));
Run Code Online (Sandbox Code Playgroud)

  • @B_Cbk 看来您已经在运行 SQL Server 2016,为什么不将数据库的兼容级别更新为 130,以便可以利用“OPENJSON”?在 SSMS 中只需要大约 5 秒 - 而且我不知道有任何重大的兼容性问题要求人们坚持使用 120。 (3认同)
  • 呵呵 - [有趣的技术](https://devblogs.microsoft.com/dotnet/announcing-ef8-preview-4/) - 我总是求助于定义我自己的“CREATE TYPE AS TABLE”类型并通过 TVP 数据传递`SqlCommand` + `SqlMetaData` - 因此使用 `OPENJSON` 具有相当大的优势,因为它不需要静态定义的类型 - 并且让我们更加临时 - 尽管他们承认 `WHERE IN` 可能会更快,但我'我很好奇“OPENJSON”的性能与 TVP 相比,对于 RBAR 来说太大的数据集,而对于“SqlBulkCopy”来说又不够大(例如,大约 20 到 5,000 行之间) (2认同)