linq 在EF Core 3.1中的Where()中使用Any()[重复]

v7pvogib  于 2023-03-27  发布在  其他
关注(0)|答案(2)|浏览(326)

此问题在此处已有答案

EntityFramework - contains query of composite key(12个答案)
3天前关闭.

await this.dbContext
          .UserTeams
          .Where(ut =>
                   teamMembers.Any(tm => tm.UserId == ut.UserId 
                                         && ut.TeamId == tm.TeamId))
          .ToListAsync();

这里teamMember是一个简单的列表,其中包含分组的UserIdsTeamIds。如果我使用Contains(),但UserIdTeamId是这里的组合键,则可以工作。
这是一个相当简单的查询,无法翻译。
错误:

System.InvalidOperationException: The LINQ expression 'DbSet<UserTeam>
     .Where(u => __teamMembers_0
         .Any(tm => u.TeamId == tm.TeamId && u.UserId == tm.UserId))' 
could not be translated. 
Either rewrite the query in a form that can
be translated, or switch to client evaluation explicitly by inserting
a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or
ToListAsync()
0sgqnhkj

0sgqnhkj1#

问题是EF不能转换复杂的对象。EF只能转换SQL参数中的.NET内存对象,并在SQL查询中使用这些SQL参数。
我看到了一个可能有效的选项。由于您只对组合值进行简单的查找,因此您可以尝试在单个SQL参数中转换user-id/team-id组合。例如,值为“-”的字符串。我假设您的id是简单的整数。如果它们是字符串,那么一个不同的分隔符可能是必要的。使用这个组合值在你的数据库源中查找任何匹配。
下面的代码未经测试,可能无法工作。另一种方法是创建某种视图,以在数据库端创建组合值。

var memberIds = teamMembers.Select(tm => $"{tm.UserId}-{tm.TeamId}").ToArray();
    await this.dbContext
              .UserTeams
              .Where(ut => memberIds.Contains(
                               SqlFunctions.StringConvert((double?)tm.UserId) + "-" +
                               SqlFunctions.StringConvert((double?)tm.TeamId)
                           )
                    )
              .ToListAsync();
oxcyiej7

oxcyiej72#

我采纳了马尔滕的想法,编写了下一个可行的代码

var idsToFilter = teamMembers.Select(tm => $"{tm.UserId}{tm.TeamId}").ToList();

            
await dbContext.UserTeams
    .Where(ut => idsToFilter.Contains(ut.UserId.ToString() + ut.TeamId.ToString()))
    .ToListAsync();

在Where子句中使用Contains,我可以过滤teamMembers中的UserTeams。你必须注意到,我要过滤的字符串(在Contains中)必须与Select子句中的字符串相同。

相关问题