Проверьте, содержит ли список элемент из другого списка в EntityFramework

У меня есть объект 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 поисковых запросов и человека с 5-10 местами. Проблема заключается в том, что у некоторых людей может быть 100 мест, а поиск также может быть в 100 местах одновременно. выполнить вышеописанный EF фактически создал SQL-запрос 2000+ и завершился неудачно, потому что он слишком глубоко вложен. В то время как вложенность уже сама по себе является проблемой, даже если бы это сработало, мне все равно не было бы очень повезло бы с SQL-запросом 2000+.

Примечание: реальный код также включает в себя несколько уровней и отношения родитель-потомок, но мне удалось получить его до этой довольно плоской структуры, используя только id, а не полные объекты

Каким будет лучший способ выполнить это в EF?

Ответ 1

Я предлагаю:

var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searachIds.Contains(l.Id)));

Contains будет переведен в оператор IN.

Имейте в виду, что список id входит в оператор sql. Если ваш список идентификаторов огромен, тогда вы получите огромный запрос.

Ответ 2

Попробуйте переключиться на соединения, а не массивные данные:

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

Я ожидаю, что для создания более дружественного плана выполнения.