我有一个实体Person,它有一个与之关联的位置列表。我需要查询人员表并从位置列表(标准)中获取至少有一个位置的所有人员。以下工作但效率很低:
var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searchIds.Any(id => l.Id == id)));
这适用于小型列表(例如5-10个searchIds和5-10个位置的人。问题是有些人可能有100个位置,搜索也可以同时在100个位置。当我尝试执行上面的EF实际上产生了一个2000+的SQL语句而失败了,因为它嵌套太深了。虽然嵌套本身已经是一个问题,即使它可以工作,我仍然不会发生2000+ SQL语句
注意:真实代码还包括多个级别和父子关系,但我确实设法使用id而不是完整对象将其归结为这个相当扁平的结构
在EF中实现这一目标的最佳方法是什么?
答案 0 :(得分:49)
我会建议:
var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searchIds.Contains(l.Id)));
Contains
将被翻译为IN
声明。
请记住,id列表会进入sql语句。如果你的id列表很大,那么你最终会得到一个巨大的查询。
答案 1 :(得分:5)
尝试切换到联接而不是执行大量数据包括:
var searchIds = new List<int>{1,2,3,4,5};
var results = (from p in persons
join l in Location on p.PersonId equals l.PersonId
where searchIds.Contains(l.Id)
select p).Distinct().ToList();
显然修复此行以匹配您的类和/或加入属性。
join l in Location on p.PersonId equals l.PersonId
我希望能够生成更友好的执行计划。