Comment travailler autour d'EF générant une instruction SQL nestede trop profondément

J'utilise un model auto-référencé dans Entity Framework 6, à partir duquel je dois sélectionner des instances, en fonction d'une sélection effectuée par l'user. Pour les sélections plus importantes, j'obtiens une exception: "Une partie de votre instruction SQL est nestede trop profondément: réécrivez la requête ou divisez-la en plus petites requêtes."

Ceci est une version simplifiée de mon model:

public class Hierarchy { public int Id { get; set; } public ssortingng Name { get; set; } public int? ParentId { get; set; } public virtual Hierarchy Parent { get; set; } public virtual ICollection<Hierarchy> Children { get; set; } } 

La sélection par l'user contient un certain nombre d'ID.

Ma database est ensemencée avec

 Id Name ParentId 1 Root NULL 2 parent-1 1 3 item-1-1 2 4 item-1-2 2 5 parent-2 1 6 item-2-1 2 7 item-2-2 2 8 child-1-1-1 3 9 child-1-1-2 3 10 child-1-2-1 4 11 child-1-2-2 4 12 child-2-1-1 3 13 child-2-1-2 3 14 child-2-2-1 4 15 child-2-2-2 4 

J'ai besoin de récupérer les instances sélectionnées elles-mêmes, ainsi que les parents et les enfants des instances sélectionnées. Le problème est dans la sélection des parents. C'est une requête Linq, qui fait cela:

 public static List<Hierarchy> Select(List<int> selection) { var result = context.Hierarchy .Where(sub => sub.Children.Select(csub => csub.Id).Intersect(selection).Any()); } 

Malheureusement, il est converti en une instruction SQL laide. En appelant

 var test = Hierarchy.Select(new List<int>() { 2, 6, 11 }); 

ceci est converti en:

 SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name], [Extent1].[ParentId] AS [ParentId] FROM [dbo].[Hierarchy] AS [Extent1] WHERE EXISTS (SELECT 1 AS [C1] FROM (SELECT [Extent2].[Id] AS [Id] FROM [dbo].[Hierarchy] AS [Extent2] WHERE [Extent1].[Id] = [Extent2].[ParentId] INTERSECT SELECT [UnionAll2].[C1] AS [C1] FROM (SELECT [UnionAll1].[C1] AS [C1] FROM (SELECT 2 AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable1] UNION ALL SELECT 6 AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1] UNION ALL SELECT 11 AS [C1] FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]) AS [Intersect1] ) 

Un niveau de sous-requêtes UnionAll<n> est ajouté pour chaque identifiant de la sélection. En pratique, l'user peut sélectionner plusieurs identifiants. Quand il y a plus de 40 id, je tombe sur une abstraction qui fuit et j'obtiens l'exception. Dans tous les cas, cela ressemble à une requête sous-optimale.

Essentiellement, ma requête doit find toutes les instances qui ont l'un des éléments sélectionnés en tant qu'enfant. Cela implique de déterminer, pour chaque instance, l'intersection de deux lists: une list locale des identifiants sélectionnés et la list des enfants de chaque instance dans la database.

Quelqu'un peut-il penser à un moyen de faire cela avec Linq pour les entités, sans émettre de requête pour chaque élément sélectionné?

peut être

 public static List<Hierarchy> Select(List<int> selection) { var result = context.Hierarchy .Where(sub => sub.Children.Any(csub => selection.Contains(csub.Id))); }