在从EFCore2.2升级到EFCore3.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();在EFCore3.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)作为第二个查询中的子查询,以便将其转换为:
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发布于 2021-05-23 21:53:01
尝试将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 2以前在内存中执行过这种过滤--请参阅自动静默客户端评估破变
旧行为 在3.0之前,当Before无法将查询的一部分表达式转换为SQL或参数时,它会在客户端上自动计算表达式。默认情况下,客户端对可能昂贵的表达式的计算只会触发警告。新行为 从3.0开始,EF只允许在客户端上计算顶层投影(查询中的最后一个Select()调用)中的表达式。当查询的任何其他部分中的表达式无法转换为SQL或参数时,将引发异常。
https://stackoverflow.com/questions/67664656
复制相似问题