Почему во внутреннем SQL запроса Entity Framework linq нет предложения GroupBy? - PullRequest
3 голосов
/ 10 июля 2020

В документации Entity Framework: https://www.entityframeworktutorial.net/querying-entity-graph-in-entity-framework.aspx

в разделе, посвященном GroupBy, мы можем прочитать следующий код:

using (var ctx = new SchoolDBEntities())
{    
    var students = from s in ctx.Students 
                group s by s.StandardId into studentsByStandard
                select studentsByStandard;

    foreach (var groupItem in students)
    {
        Console.WriteLine(groupItem.Key);

        foreach (var stud in groupItem)
        {
            Console.WriteLine(stud.StudentId);
        }
    }
}

выполняется внутренне после SQL :

SELECT 
[Project2].[C1] AS [C1], 
[Project2].[StandardId] AS [StandardId], 
[Project2].[C2] AS [C2], 
[Project2].[StudentID] AS [StudentID], 
[Project2].[StudentName] AS [StudentName], 
[Project2].[StandardId1] AS [StandardId1]
FROM ( SELECT 
    [Distinct1].[StandardId] AS [StandardId], 
    1 AS [C1], 
    [Extent2].[StudentID] AS [StudentID], 
    [Extent2].[StudentName] AS [StudentName], 
    [Extent2].[StandardId] AS [StandardId1], 
    CASE WHEN ([Extent2].[StudentID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
    FROM   (SELECT DISTINCT 
        [Extent1].[StandardId] AS [StandardId]
        FROM [dbo].[Student] AS [Extent1] ) AS [Distinct1]
    LEFT OUTER JOIN [dbo].[Student] AS [Extent2] ON ([Distinct1].[StandardId] = [Extent2].                                                [StandardId]) OR (([Distinct1].[StandardId] IS NULL) AND ([Extent2].[StandardId] IS NULL))
)  AS [Project2]
ORDER BY [Project2].[StandardId] ASC, [Project2].[C2] ASC
go

Почему в SQL нет предложения GroupBy? Если предложение GroupBy не требуется, не можем ли мы просто использовать простой Select с OrderBy и без Joins? Может ли кто-нибудь объяснить вышеуказанный вопрос?

1 Ответ

4 голосов
/ 10 июля 2020

Итог: потому что SQL не может возвращать вложенные наборы результатов.

Каждый оператор SQL SELECT возвращает плоский список значений. LINQ может возвращать графы объектов, то есть объекты с вложенными объектами. Это именно то, что делает LINQ GroupBy.

В SQL оператор GROUP BY возвращает только столбцы группировки и агрегированные результаты:

SELECT StandardId, COUNT(*)
FROM Students
GROUP BY StandardId;

Остальные столбцы студентов

Оператор LINQ GroupBy возвращает что-то вроде

StandardId
            StudentId StudentName
1
            21        "Student1"
            15        "Student2"
2
            48        "Student3"
            91        "Student4"
            17        "Student5"

Следовательно, оператор SQL GROUP BY никогда не может быть источником для LINQ GroupBy.

Entity Framework (6) знает это и генерирует оператор SQL, который извлекает все необходимые данные из базы данных, добавляет некоторые части, которые упрощают группировку, и создает группировку на стороне клиента.

...