c# - 在 EF Core 2 中使用 Contains as (NOT) EXIST 不再适用于 EF Core 3.1
问题描述
从 EF Core 2.2 升级到 EF Core 3.1 后,我遇到了“不再在客户端上评估 LINQ 查询”问题。
我在 2.2 中有以下查询,它们工作正常:
var entQry = await
(from up in _dbContext.Profiles
join pa in _dbContext.Access
on up.ProfileId equals pa.ProfileId
where (up.IdentityUserId == identityUser.Id)
select new
{
pa.LibraryId
}).ToListAsync();
var libQry = await
(from en in _dbContext.Entities
join pa in _dbContext.Access
on en.LibraryId equals pa.ObjectId
where (up.IdentityUserId == identityUser.Id
&& !entQry.Contains(new { en.LibraryId }))
select new
{
Id = en.Id
}).ToListAsync();
在 EF Core 3.1 中,第二个查询在 Contains 方法上失败,并出现“无法翻译”错误。经过反复试验,我将其重写如下:
var libQry2 = await
(from en in _dbContext.Entities
join pa in _dbContext.Access
on en.LibraryId equals pa.ObjectId
where (up.IdentityUserId == identityUser.Id)
select new
{
Id = en.Id
}).ToListAsync();
var libQry = libQry2.Where(w => !entQry.Any(c => c.LibraryId == w.Id));
现在虽然这可行,但这不是我想要的,因为我希望在服务器上执行整个查询。那可能吗?
我可以将第一个查询 (entQry) 作为第二个查询中的子查询,以便将其转换为 SQL:
SELECT en.Id
FROM Entities en JOIN Access pa ON en.LibraryId equals pa.ObjectId
WHERE x.id NOT IN (SELECT up.LibraryId FROM Profiles up JOIN Access pa ON up.ProfileId = pa.ProfileId)
AND up.IdentityUserId == @identityUser.Id
解决方案
尝试使用Contains
“原始”类型的集合:
var entIds = await
(from up in _dbContext.Profiles
join pa in _dbContext.Access
on up.ProfileId equals pa.ProfileId
where (up.IdentityUserId == identityUser.Id)
select pa.LibraryId)
.ToListAsync();
var libQry = await
(from en in _dbContext.Entities
join pa in _dbContext.Access
on en.LibraryId equals pa.ObjectId
where (up.IdentityUserId == identityUser.Id
&& !entIds.Contains(en.LibraryId))
select new
{
Id = en.Id
}).ToListAsync();
此外,我非常确定 EF Core 2 之前在内存中执行了此过滤 - 请参阅自动静默客户端评估重大更改:
旧行为
在 3.0 之前,当 EF Core 无法将作为查询的一部分的表达式转换为 SQL 或参数时,它会自动评估客户端上的表达式。默认情况下,客户端对可能昂贵的表达式的评估只会触发警告。
新行为
从 3.0 开始,EF Core 仅允许在客户端评估顶级投影(查询中的最后一个 Select() 调用)中的表达式。当查询的任何其他部分中的表达式无法转换为 SQL 或参数时,将引发异常。
推荐阅读
- angular - 在动态组件加载中导航时如何跟踪组件
- vue.js - 如何访问自定义组件中的数据?
- c++11 - 这是 Qt Creator 分析器中的错误吗
- java - Java:从链表中查找和删除元素的最佳方法
- intellij-idea - Dart SDK 在哪里?| 错误:指定为 Dart SDK home 的文件夹不存在
- javascript - 将图标附加到按钮
- sql-server - 从 SQL Server 按天提取数据
- android - 弹出软键盘时布局不调整
- java - 更新组件的高度也会改变它的宽度
- javascript - 我正在尝试将 javascript Number 类型转换为 BIGINT 以传递给 Postgres 表