在EF Core 3.1的Where()中使用Any()

时间:2020-04-06 13:10:00

标签: c# linq ef-core-3.1

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()

1 个答案:

答案 0 :(得分:1)

问题在于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();