2014-11-26 27 views
8

Tôi có một cấu trúc bảng đơn giản của dịch vụ với mỗi một số cơ sở. Trong cơ sở dữ liệu, đây là bảng Service và bảng Facility, trong đó bảng Facility có tham chiếu đến một hàng trong bảng Dịch vụ.Tại sao sự kết hợp này của Select, Where và GroupBy gây ra một ngoại lệ?

Trong ứng dụng của chúng tôi, chúng tôi có LINQ làm việc tiếp theo:

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

Nhưng vì những lý do ngoài tầm kiểm soát của tôi, bộ nguồn dự kiến ​​sẽ là một đối tượng phi thực thể trước khi Where cuộc gọi, theo cách này:

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

Nhưng điều này làm tăng ngoại lệ sau đây, không có ngoại lệ bên trong:

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

Loại bỏ các Where, tuy nhiên, làm cho nó hoạt động, mà làm cho tôi tin rằng đó là chỉ kết hợp cụ thể này của phương pháp gọi:

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ó cách nào để làm cho công việc trên: chọn một phi thực thể và sau đó sử dụng WhereGroupBy trên kết quả có thể truy vấn? Thêm ToList sau khi tác phẩm Select hoạt động, nhưng tập hợp nguồn lớn làm cho điều này không khả thi (nó sẽ thực thi truy vấn trên cơ sở dữ liệu và sau đó thực hiện logic nhóm trong C#).

+0

Và chúng tôi đang nói về cơ sở dữ liệu và phiên bản EF nào? –

+0

SQL Server 2014 và khung thực thể 6.1.1! –

+1

Làm cho phần câu hỏi này của [LINQ-to-entites của tôi! = LINQ-to-objects collection] (http://stackoverflow.com/a/13352779/861716). –

Trả lời

11

ngoại lệ này bắt nguồn từ đoạn mã này trong nguồn 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; 
} 

Tôi phải thừa nhận: nó không phải là rõ ràng những gì xảy ra ở đây và không có hồ sơ thiết kế kỹ thuật tiết lộ tất cả các chiến lược xây dựng truy vấn của EF . Nhưng đoạn mã này ...

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

Cung cấp một chút nhìn phía sau màn cửa. Tôi vừa thử một số OrderBy trong trường hợp của riêng tôi đã sao chép chính xác của bạn và nó đã hoạt động. Vì vậy, tôi chắc chắn rằng nếu bạn làm ...

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

ngoại lệ sẽ biến mất.

+0

Điều này khắc phục vấn đề hoàn toàn, rực rỡ! Cảm ơn bạn đã đào sâu vào mã nguồn, điều đó không rõ ràng đối với tôi, nơi để tìm ngoại lệ. –

Các vấn đề liên quan