У меня есть следующий запрос 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 )
, но не уверен, как это сделать в соединении.
Есть ли лучший способ написать этот запрос?