如何通过单条LINQ表达式根据Line ID列表查询匹配的Translation记录
解决方案
你初始写法的问题在于lines是List<Line>类型的集合,不存在直接的Id属性,无法直接与t.LineId做相等判断。根据你的需求可以分两种场景实现:
场景1:仅查询所有匹配的Translation记录
如果只需要获取所有LineId属于lines列表Id集合的Translation数据,不需要保持和lines列表的顺序对应、也不需要每个Line单独取第一条匹配项,使用Contains方法即可。EF Core会自动生成SQL的IN子句,单次查询完成拉取,避免循环查库的N+1性能问题:
var targetLineIds = lines.Select(l => l.Id).ToList(); var translations = _context.Translations .Where(t => targetLineIds.Contains(t.LineId)) .ToList();
场景2:与你提供的foreach逻辑完全等价
你给出的循环逻辑有三个明确特征:
- 返回结果长度和lines集合长度完全一致
- 结果顺序和lines的遍历顺序完全对齐
- 每个Line对应取第一条匹配的Translation,无匹配时对应位置存入null
要实现该效果同时仅触发一次数据库查询,可以先一次性拉取所有匹配的Translation到内存,再按原lines顺序做映射:
var targetLineIds = lines.Select(l => l.Id).ToList(); // 单次查询拉取所有关联数据 var matchedTranslations = _context.Translations .Where(t => targetLineIds.Contains(t.LineId)) .ToList(); // 内存映射对齐原顺序,逻辑和foreach完全一致 var translations = lines .Select(line => matchedTranslations.FirstOrDefault(t => t.LineId == line.Id)) .ToList();
提示:避免直接在循环中执行数据库查询,该写法会产生N+1查询问题,数据量较大时性能损耗非常明显。
内容的提问来源于stack exchange,提问作者Drago
相关产品推荐
相关产品推荐

