2017-06-23 2 views
-1

Wie kann ich eine richtige Join durchführen? Ich versuche, die DefaultIfEmpty() Funktion zu verwenden, aber ohne Wirkung.Outer right beitreten auf Linq C#

Es ist mein Code:

var AbsByDepartmentADM = (from abs in _dbContext.Absences 
           join e in _dbContext.DepartementProjects on abs.DepartementProjectID equals e.Id 

           into g 

           from c in g.DefaultIfEmpty() 
            where abs.Profil == "SHT" 

            group abs by new { abs.DepartementProject.Label } into z 
           select new 
           { 
            Matricule = z.Key.Label, 
            NumberOfAbsence = z.Count(), 
            WorkedHours = z.Sum(a => a.WorkedHours), 
            AbsencesHours = (8* z.Count() - z.Sum(a => a.WorkedHours)) 

           } into H 

           orderby H.NumberOfAbsence descending 
           select H); 

Die SQL-Abfrage generiert:

{SELECT 
[Project1].[C3] AS [C1], 
[Project1].[Label] AS [Label], 
[Project1].[C1] AS [C2], 
[Project1].[C2] AS [C3], 
[Project1].[C4] AS [C4] 
FROM (SELECT 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[A2] AS [C2], 
1 AS [C3], 
CAST(8 * [GroupBy1].[A3] AS float) - [GroupBy1].[A4] AS [C4], 
[GroupBy1].[K1] AS [Label] 
FROM (SELECT 
    [Extent2].[Label] AS [K1], 
    COUNT(1) AS [A1], 
    SUM([Extent1].[WorkedHours]) AS [A2], 
    COUNT(1) AS [A3], 
    SUM([Extent1].[WorkedHours]) AS [A4] 
    FROM [dbo].[Absences] AS [Extent1] 
    INNER JOIN [dbo].[DepartementProjects] AS [Extent2] ON [Extent1].[DepartementProjectID] = [Extent2].[Id] 
    WHERE N'SHT' = [Extent1].[Profil] 
    GROUP BY [Extent2].[Label] 
) AS [GroupBy1] 
) AS [Project1] ORDER BY [Project1].[C1] DESC} 

Die SQL-Abfrage zu erwarten:

{SELECT 
[Project1].[C3] AS [C1], 
[Project1].[Label] AS [Label], 
[Project1].[C1] AS [C2], 
[Project1].[C2] AS [C3], 
[Project1].[C4] AS [C4] 
FROM (SELECT 
    [GroupBy1].[A1] AS [C1], 
    [GroupBy1].[A2] AS [C2], 
1 AS [C3], 
CAST(8 * [GroupBy1].[A3] AS float) - [GroupBy1].[A4] AS [C4], 
[GroupBy1].[K1] AS [Label] 
FROM (SELECT 
    [Extent2].[Label] AS [K1], 
    COUNT(1) AS [A1], 
    SUM([Extent1].[WorkedHours]) AS [A2], 
    COUNT(1) AS [A3], 
    SUM([Extent1].[WorkedHours]) AS [A4] 
    FROM [dbo].[Absences] AS [Extent1] 
    RIGHT JOIN [dbo].[DepartementProjects] AS [Extent2] ON [Extent1].[DepartementProjectID] = [Extent2].[Id] 
    WHERE N'SHT' = [Extent1].[Profil] 
    GROUP BY [Extent2].[Label] 
) AS [GroupBy1] 
) AS [Project1] ORDER BY [Project1].[C1] DESC} 
+1

Hinweis: Eine rechte äußere Verknüpfung ist eine [linke äußere] (https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-left-outer-joins) mit der linken rechts und umgekehrt. – spender

+0

Vergessen Sie Joins in EF - Navigationseigenschaften verwenden. Das hast du schon an einem Ort gemacht - 'abs.DepartementProject', was den' INNER JOIN' erzeugt, den du in der SQL-Abfrage siehst. Da Sie die Variable "c" nicht in Ihrer LINQ-Abfrage verwenden, wird der explizite Join (linkes äußeres BTW) einfach vom EF-Abfrageübersetzer ignoriert. –

+0

Was passiert, wenn Sie 'von c in g.DefaultIfEmpty()' in 'von abs in g.DefaultIfEmpty()' ändern? Siehe https://stackoverflow.com/a/3413732/34092. – mjwills

Antwort

0
var AbsByDepartmentADM = from department in _dbContext.DepartementProjects 
           join abs in _dbContext.Absences on department.Id equals abs.DepartementProjectID into groupedResult 
           from groupedResultRight in groupedResult.DefaultIfEmpty() 
           group groupedResultRight by department.Label into grouped 
           let NumberOfAbsence = grouped.Count(t => t.DepartementProjectID != null) 
           let WorkedHours = grouped.Sum(a => a.WorkedHours != null ? a.WorkedHours : 0) 

           select new 
           { 
            DepartmentId = grouped.Key, 
            NumberOfAbsence, 
            WorkedHours, 
            AbsencesHours = (8 * NumberOfAbsence - WorkedHours) 
           }; 
0

Die Verbindung scheint keinen Zweck zu dienen in Ihrem LINQ-Code, also vereinfachte ich und entfernte einige eigenartige Verwendung. Ich habe let verwendet, um DRY zu sein, aber es ist möglicherweise nicht effizienter für IQueryable, ich bin mir nicht sicher.

var AbsByDepartmentADM2 = from abs in _dbContext.Absences 
         where abs.Profil == "SHT" 
         group abs by abs.DepartementProject.Label into absg 
         let NumberOfAbsence = absg.Count() 
         let WorkedHours = absg.Sum(abs => abs.WorkedHours) 
         orderby NumberOfAbsence descending 
         select new { 
          Matricule = absg.Key, 
          NumberOfAbsence, 
          WorkedHours, 
          AbsencesHours = (8 * NumberOfAbsence - WorkedHours) 
         }; 
+0

danke für deinen Vorschlag, aber, ich habe immer noch das gleiche Problem, meine Erwartung ist es, alle Abteilungen zu zeigen, auch wenn die Anzahl null ist, –