C# 在EF Core 2中使用包含作为(不)存在在EF Core 3.1中不再有效

C# 在EF Core 2中使用包含作为(不)存在在EF Core 3.1中不再有效,c#,linq,migration,ef-core-3.1,C#,Linq,Migration,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 == identityUse

从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方法的第二次查询失败,出现“cannot translate”错误。经过反复试验,我将其改写如下:

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=wait
(在_dbContext.Profiles中从上到下)
在_dbContext.Access中加入pa
on up.ProfileId等于pa.ProfileId
其中(up.identityUser.Id==identityUser.Id)
选择pa.LibraryId)
.ToListAsync();
var libQry=wait
(来自en in_dbContext.Entities)
在_dbContext.Access中加入pa
关于en.LibraryId等于pa.ObjectId
其中(up.identityUser.Id==identityUser.Id
&&!entIds.Contains(en.LibraryId))
选择新的
{
Id=en.Id
}).ToListAsync();
另外,我非常确定EF Core 2以前在内存中执行过此过滤-请参阅自动静默客户端评估:

旧行为

在3.0之前,当EF Core无法将作为查询一部分的表达式转换为SQL或参数时,它会自动在客户端计算表达式。默认情况下,对潜在昂贵表达式的客户端计算只会触发警告

新行为

从3.0开始,EF Core只允许在客户机上计算顶级投影(查询中的最后一个Select()调用)中的表达式。当查询的任何其他部分中的表达式无法转换为SQL或参数时,将引发异常


谢谢我不得不调整这些类型的查询并测试它们,现在它们都通过了。我很确定你是对的,2.2版本在客户端部分执行。正是这种行为使许多人退回到使用FromSqlRaw或类似的方法,以便得到一个简单的查询,使其按预期工作,但这是另外一种讨论。现在我必须去寻找我的ajax调用突然被404弄得到处都是的原因…@RJD很乐意帮忙!就我个人而言,我总是为调试启用查询日志记录,并且在编写新查询时尝试检查实际生成的内容,尽管根据我的经验,EF在通常生成非常好的查询方面非常出色(尽管显然存在一些异常值,这导致了我知道的方法use=)。