2014-11-26 13 views
8

Ho una semplice struttura a tabelle di servizi con ciascuna un numero di servizi. Nel database, questa è una tabella Service e una tabella Facility, in cui la tabella Facility ha un riferimento a una riga nella tabella Servizio.Perché questa combinazione di Select, Where e GroupBy causa un'eccezione?

Nella nostra applicazione, abbiamo la seguente LINQ di lavoro:

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

Ma per ragioni indipendenti dalla mia volontà, il set di fonte è proiettata ad un oggetto non-entità prima della chiamata Where, in questo modo:

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() }) 

Ma ciò solleva la seguente eccezione, senza alcuna eccezione interna:

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

Rimozione del Where, però, lo fa funzionare, il che mi fa credere che è solo in questa specifica combinazione di metodo di chiamate:

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() }) 

C'è un modo per rendere il lavoro di cui sopra: selezionare per una non-entità oggetto e quindi utilizzare Where e GroupBy sul risultante interrogabile? L'aggiunta di ToList dopo il Select funziona, ma l'insieme di sorgenti di grandi dimensioni rende questo non fattibile (eseguirà la query sul database e quindi eseguirà la logica di raggruppamento in C#).

+0

E di quale database e versione EF stiamo parlando? –

+0

SQL Server 2014 e Entity Framework 6.1.1! –

+1

Questa domanda fa parte della mia raccolta [LINQ-to-enter! = LINQ-to-objects] (http://stackoverflow.com/a/13352779/861716). –

risposta

11

Questa eccezione ha origine da questo pezzo di codice nel sorgente EF ...

// <summary> 
// 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. 
// </summary> 
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(Strings.ADP_NestingNotSupported(op.OpType.ToString(), chi.Op.OpType.ToString())); 
     } 
    } 
    return n; 
} 

devo ammetterlo: non è ovvio ciò che accade qui e non c'è nessun documento tecnico di progettazione divulgare tutte le strategie di creazione di query di EF . Ma questo pezzo di codice ...

// 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(Strings.ADP_KeysRequiredForJoinOverNest(op.OpType.ToString())); 
     } 
    } 
} 

Dà una sbirciatina dietro le tende. Ho appena provato uno OrderBy in un mio caso che ha riprodotto esattamente il tuo, e ha funzionato. Quindi sono abbastanza sicuro che se lo fai ...

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'eccezione sarà andata.

+0

Questo ha risolto il problema completamente, brillante! Grazie per aver scavato nel codice sorgente, non era ovvio per me dove guardare dato l'eccezione. –