2014-11-26 10 views
8

Mam prostą strukturę tabel usług z każdym z wielu urządzeń. W bazie danych jest to tabela Service i tabela Facility, gdzie tabela Facility odwołuje się do wiersza w tabeli Usługa.Dlaczego ta kombinacja Select, Where i GroupBy powoduje wyjątek?

W naszej aplikacji, mamy następujące LINQ pracy:

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

ale z przyczyn ode mnie niezależnych, zbiór źródłowy jest rzutowany na obiekt bez jednostki przed wywołaniem Where w ten sposób:

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

Ale tu pojawia się następujący wyjątek, bez wyjątku wewnętrznym:

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

Wyjmowanie Where jednak sprawia, że ​​praca, która sprawia mi wierzyć, że to tylko w tej konkretnej kombinacji metody połączeń:

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

Czy istnieje sposób, aby powyższy pracy: wybierz się do braku podmiotu obiekt, a następnie użyć Where i na wynikowym zapytaniu? Dodanie ToList po Select działa, ale duży zestaw źródeł sprawia, że ​​jest to niewykonalne (wykonałoby zapytanie w bazie danych, a następnie logikę grupującą w języku C#).

+0

O której wersji i wersji EF mówimy? –

+0

SQL Server 2014 i Entity Framework 6.1.1! –

+1

To pytanie stanowi część mojej kolekcji [LINQ-to-entites! = LINQ-to-Object] (http://stackoverflow.com/a/13352779/861716). –

Odpowiedz

11

Wyjątek ten wywodzi się z tego kawałka kodu w źródle 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; 
} 

muszę przyznać, że nie jest oczywiste, co dzieje się tu i tam ma projekt techniczny dokument ujawniający wszystkie strategie budowania zapytań EF . Ale ten fragment kodu ...

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

Daje trochę zerknięcia za zasłony. Właśnie wypróbowałem OrderBy w moim własnym, który dokładnie powielał twoje, i zadziałało. Więc jestem pewien, że jeśli to zrobisz ...

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

wyjątek zniknie.

+0

Naprawiono problem całkowicie, genialnie! Dziękuję za wkopanie się w kod źródłowy, nie było dla mnie oczywiste, gdzie szukać, biorąc pod uwagę wyjątek. –

Powiązane problemy