首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在EF Core 2中使用Contains (NOT)不再适用于EF Core 3.1

在EF Core 2中使用Contains (NOT)不再适用于EF Core 3.1
EN

Stack Overflow用户
提问于 2021-05-23 21:45:02
回答 1查看 81关注 0票数 1

在从EFCore2.2升级到EFCore3.1之后,我遇到了"LINQ查询不再对客户端进行评估“的问题。

我在2.2中有以下查询,它们工作得很好:

代码语言:javascript
复制
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方法上失败,出现“无法翻译”错误。经过一些试验和错误之后,我将其改写如下:

代码语言:javascript
复制
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)作为第二个查询中的子查询,以便将其转换为:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-23 21:53:01

尝试将Contains与“基元”类型的集合一起使用:

代码语言:javascript
复制
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或参数时,将引发异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67664656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档