J'ai une personne d'entité qui a une liste d'emplacements qui lui sont associés. Je dois interroger la table des personnes et obtenir tous ceux qui ont au moins un emplacement dans une liste d'emplacements (critères). Ce qui suit fonctionne mais est très inefficace:
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)));
Cela fonctionne bien pour les petites listes (disons 5-10 searchIds et une personne avec 5-10 emplacements. Le problème est que certaines personnes peuvent avoir 100 emplacements et une recherche peut également être pour 100 emplacements à la fois. Lorsque j'ai essayé d'exécuter ce qui précède EF a en fait produit une instruction SQL 2000+ et a échoué car il était trop profondément imbriqué. Bien que l'imbrication soit déjà un problème en soi, même si cela fonctionnerait, je ne serais toujours pas très arrivé avec une instruction SQL 2000+.
Remarque: le vrai code comprend également plusieurs niveaux et relations parent-enfant, mais j'ai réussi à le réduire à cette structure assez plate en utilisant uniquement des identifiants, au lieu d'objets complets
Quelle serait la meilleure façon d'y parvenir dans EF?
Je proposerai:
var searchIds = new List<int>{1,2,3,4,5};
var result = persons.Where(p => p.Locations.Any(l => searchIds.Contains(l.Id)));
Contains
sera traduit en instruction IN
.
Gardez à l'esprit que la liste des identifiants va dans l'instruction sql. Si votre liste d'ID est énorme, vous finirez par avoir une énorme requête.
Essayez de basculer vers des jointures au lieu de procéder à une collecte massive de données:
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();
Évidemment, corrigez cette ligne pour qu'elle corresponde à vos classes et/ou rejoignez la propriété.
join l in Location on p.PersonId equals l.PersonId
Je m'attendrais à ce que cela génère un plan d'exécution plus convivial.