Преобразование сложного SQL-запроса в LINQ-to-SQL - PullRequest
0 голосов
/ 02 июля 2019

У меня есть следующий запрос SQL - который включает в себя несколько левых соединений и внутренних запросов, мне нужно преобразовать его в LINQ-to-SQL.

INSERT INTO @BranchStatus
SELECT
    b.BranchId
    ,b.BranchName
    ,AVG(CASE WHEN l.[Status] = 1 THEN DATEDIFF(SECOND, l.AddedTime, GETUTCDATE()) ELSE NULL END) AS CurrentWaitTime
    ,SUM(CASE WHEN l.[Status] = 1 THEN 1 ELSE 0 END) AS WaitingInLobby
    ,SUM(CASE WHEN l.[Status] = 5 THEN 1 ELSE 0 END) AS TotalAssists
    ,SUM(CASE WHEN l.[Status] = 6 THEN 0 ELSE sp.ServiceCount END) AS TotalPSProvided
    ,AVG(CASE WHEN l.[Status] = 5 THEN DATEDIFF(SECOND, l.AssistedTime, l.CompletedTime) ELSE NULL END) AS AverageAssistTime
    ,AVG(CASE WHEN l.[Status] = 5 THEN DATEDIFF(SECOND, l.AddedTime, l.AssistedTime) ELSE NULL END) AS AverageWaitTime
    ,SUM(CASE WHEN l.[Status] = 6 THEN 1 ELSE 0 END) AS TotalAbandons
FROM Branch b
    LEFT JOIN Lobby l ON b.BranchId = l.FkBranchId
    LEFT JOIN (SELECT FkLobbyId, COUNT(*) AS ServiceCount 
        FROM ServiceProvided _sp LEFT JOIN [Service] _s ON _sp.FkServiceId=_s.ServiceID 
        WHERE _s.ShowInMemberLeft=0 AND _sp.FkLobbyId IN 
            (SELECT LobbyId FROM Lobby WHERE IsActive = 1 AND IsArchived = 0 AND (@BranchIds IS NULL OR FkBranchId in 
            (SELECT BranchId From @SelectedBranchIds))) GROUP BY _sp.FkLobbyId) sp ON l.LobbyId = sp.FkLobbyId
WHERE
    b.IsActive = 1
    AND l.IsActive = 1
    AND l.IsArchived = 0
    AND (@BranchIds IS NULL OR l.FkBranchId in (SELECT BranchId From @SelectedBranchIds))
GROUP BY b.BranchId, b.BranchName
;

Ниже приведена версия LINQ-to-SQL:

var branchStatus = (from b in context.Branches.Local join l in context.Lobbies.Local on b.BranchId equals l.BranchId into branchLobbyDetails
                           from bl in branchLobbyDetails.DefaultIfEmpty()
                           join ps1 in (from l1 in context.Lobbies.Local
                                        where l1.IsActive && !l1.IsArchived
                                            && (branches.Count == 0 || branches.Contains(l1.BranchId))
                                        select new
                                        {
                                            l1.LobbyId,
                                            ServiceCount = (from s in context.Services.Local
                                                            join sp in context.ServicesProvided.Local on s.ServiceId equals sp.ServiceId
                                                            where sp.LobbyId == l1.LobbyId && !s.ShowInLeftWithoutAssist select s.ServiceId).Count()
                                        }) on bl.LobbyId equals ps1.LobbyId
                           where b.IsActive && bl.IsActive && !bl.IsArchived 
                            && (branches.Count == 0 || branches.Contains(b.BranchId))
                            select new BranchStatusDetailsDto
                            {
                                Id = b.BranchId.ToString(),
                                BranchName = b.BranchName,
                                WaitingInLobby = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 1 select l1.LobbyId).Count().ToString(),
                                TotalAssists = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select l1.LobbyId).Count().ToString(),
                                TotalAbandons = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 6 select l1.LobbyId).Count().ToString(),
                                TotalPSProvided = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status != 6 select ps1.ServiceCount).ToString(),
                                AverageAssistTime = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select (l1.CompletedTime - l1.AssistedTime).Value.TotalSeconds).Average().ToString(),
                                AverageWaitTime = (from l1 in context.Lobbies.Local where l1.LobbyId == bl.LobbyId && l1.Status == 5 select (l1.AssistedTime - l1.AddedTime).Value.TotalSeconds).Average().ToString(),
                            }).ToList();

LINQ выдает ошибку времени выполнения на on bl.LobbyId equals ps1.LobbyId, что bl равно нулю, возможно, из-за левого соединения.Если это в предложении where, я могу проверить на null, как (bl == null ? true : bl.IsActive && !bl.IsArchived ), но не уверен, как это сделать в соединении.

Есть ли лучший способ написать этот запрос?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...