如何将发送给我进行过滤的列表与我数据库中的列表进行比较?
我的候选实体中有一个名为 CandidateLanguage 的列表。
我从外部得到一个名为 LanguageSkills 的列表来进行过滤。然后,当我获取候选人时,我想进行比较,但出现错误。
我的代码:
var entities = _context.Candidates
.Include(p => p.CandidateLanguages)
.Where(m => m.CandidateLanguages
.Any(l => languageSkills
.Any(c =>
c.LanguageId == l.LanguageId &&
c.Writing <= l.Writing &&
c.Reading <= l.Reading &&
c.Speaking <= l.Speaking
)
)
)
.AsNoTracking();
我收到的错误:
无法翻译。以可翻译的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端评估
正如评论中提到的,EF 无法像过滤器中那样翻译要使用的对象列表(语言技能)。您只能使用简单类型的集合。需要在内存中完成与内存中对象的更复杂的比较。
我们可以根据请求的语言 ID 进行初始过滤:
var languageIds = languageSkills.Select(x => x.LanguageId).Distinct().ToList();
var entities = _context.Candidates
.Include(p => p.CandidateLanguages)
.Where(m => m.CandidateLanguages
.Any(l => laungageIds.Contains(l.LanguageId)))
.AsNoTracking()
.ToList();
entities = entities
.Where(l => languageSkills.Any(c =>
c.LanguageId == l.LanguageId &&
c.Writing <= l.Writing &&
c.Reading <= l.Reading &&
c.Speaking <= l.Speaking))
.ToList();
第一个查询针对 SQL 运行并检索所选语言的所有候选语言。从那里我们在内存中过滤它以精确匹配。这种方法的警告是,这可能最终会加载大量数据。
如果您要处理大量要筛选的候选人并且技能标准数量相对合理,则更完整的方法是使用动态表达式生成器根据条件构建
Where
表达式。这将用于从您的语言技能列表中组成 (AND-AND-AND) OR (AND-AND-AND) OR (AND-AND-AND) ... 表达式。这可以使用 PredicateBuilder
来完成,或者在循环中手动编写表达式,或者使用 DynamicWhere Nuget 包之类的东西。