Pourquoi cette combinaison de Select, Where et GroupBy provoque-t-elle une exception?

J’ai une structure simple de services avec chacun un certain nombre d’installations. Dans la firebase database, il s’agit d’une table de Service et d’une table de Facility , la table de fonctions ayant une référence à une ligne de la table de service.

Dans notre application, le LINQ suivant fonctionne:

 Services .Where(s => s.Facilities.Any(f => f.Name == "Sample")) .GroupBy(s => s.Type) .Select(g => new { Type = g.Key, Count = g.Count() }) 

Mais pour des raisons indépendantes de ma volonté, l’ensemble de sources est projeté sur un object non-entité avant l’appel Where , de la manière suivante:

 Services .Select(s => new { Id = s.Id, Type = s.Type, Facilities = s.Facilities }) .Where(s => s.Facilities.Any(f => f.Name == "Sample")) .GroupBy(s => s.Type) .Select(g => new { Type = g.Key, Count = g.Count() }) 

Mais cela soulève l’exception suivante, sans exception interne:

EntityCommandCompilationException: The nested query is not supported. Operation1='GroupBy' Operation2='MultiStreamNest'

Cependant, le fait de supprimer Where fonctionne, ce qui me laisse penser que ce n’est que dans cette combinaison spécifique d’appels de méthode:

 Services .Select(s => new { Id = s.Id, Type = s.Type, Facilities = s.Facilities }) //.Where(s => s.Facilities.Any(f => f.Name == "Sample")) .GroupBy(s => s.Type) .Select(g => new { Type = g.Key, Count = g.Count() }) 

Existe-t-il un moyen de faire en sorte que ce qui précède fonctionne: sélectionnez un object non-entité, puis utilisez Where et GroupBy sur l’object interrogeable résultant? L’ajout de ToList après la Select fonctionne, mais le jeu de sources volumineux rend cette opération irréalisable (la requête serait exécutée sur la firebase database, puis la logique de regroupement en C #).

Cette exception provient de ce morceau de code dans la source EF …

 //  // Not Supported common processing // For all those cases where we don't intend to support // a nest operation as a child, we have this routine to // do the work. //  private Node NestingNotSupported(Op op, Node n) { // First, visit my children VisitChildren(n); m_varRemapper.RemapNode(n); // Make sure we don't have a child that is a nest op. foreach (var chi in n.Children) { if (IsNestOpNode(chi)) { throw new NotSupportedException(Ssortingngs.ADP_NestingNotSupported(op.OpType.ToSsortingng(), chi.Op.OpType.ToSsortingng())); } } return n; } 

Je dois admettre que ce qui se passe ici n’est pas évident et qu’il n’ya pas de document de conception technique divulguant toutes les stratégies de constitution de requêtes d’EF. Mais ce morceau de code …

 // We can only pull the nest over a Join/Apply if it has keys, so // we can order things; if it doesn't have keys, we throw a NotSupported // exception. foreach (var chi in n.Children) { if (op.OpType != OpType.MultiStreamNest && chi.Op.IsRelOp) { var keys = Command.PullupKeys(chi); if (null == keys || keys.NoKeys) { throw new NotSupportedException(Ssortingngs.ADP_KeysRequiredForJoinOverNest(op.OpType.ToSsortingng())); } } } 

Donne un petit coup d’oeil derrière les rideaux. Je viens d’essayer un OrderBy dans un cas à moi qui reproduit exactement le vôtre, et cela a fonctionné. Donc, je suis sûr que si vous le faites …

 Services .Select(s => new { Id = s.Id, Type = s.Type, Facilities = s.Facilities }) .OrderBy(x => x.Id) .Where(s => s.Facilities.Any(f => f.Name == "Sample")) .GroupBy(s => s.Type) .Select(g => new { Type = g.Key, Count = g.Count() }) 

l’exception sera parti.