Это самый эффективный способ выполнить левое внешнее объединение в LINQ, если я должен сделать следующее ...
- Фильтр таблицы 2 по дате начала и окончания.
- Все строки в таблице 1 должны остаться, даже если фильтрация таблицы 2 не возвращает строк.
- Результат должен быть сгруппирован так, чтобы столбцы из таблицы 2 суммировались.
Например (например, имена переменных кода изменены по причинам, связанным с проповедью), предполагается, что у меня есть база данных с двумя таблицами Таблица 1 содержит список дверей с кодом здания, идентификатором двери и текущим состоянием (открыт или закрыт) - основной код - код здания и идентификатор двери. Таблица 2 содержит список событий для всех дверей (событие является открытием или закрытием), а также отметку времени. Таким образом, столбцы - это строительный код, идентификатор двери, отметка времени, открытие, закрытие. Открытие и закрытие - целые числа с 1 в столбце для соответствующего события. Между двумя таблицами существует код внешнего ключа в строительном коде и идентификаторе двери.
Для моего запроса мне нужно вернуть список всех уникальных дверей с текущим состоянием двери и суммой всех событий открытия и закрытия за выбранный период времени. Запись должна быть возвращена для каждой двери, даже если в течение выбранного периода времени не произошло никаких событий.
Ниже приведен лучший код LINQ, который я смог придумать. Это работает, но кажется действительно неэффективным и трудным для понимания. Как бы вы сделали его более эффективным и легким для понимания?
var query =
from doors in Context.Doors
join fevents in
(
from events in db.Events
where events.TimeStamp >= date1 && events.TimeStamp <= date2
select new { events.BuildingCode, events.DoorID, events.TimeStamp, events.Opening, events.Closing }
)
on new { doors.BuildingCode, doors.DoorID } equals { fevents.BuildingCode, fevents.DoorID }
into g1
from c in g1.DefaultIfEmpty()
group c by new
{
doors.BuildingCode,
doors.DoorID,
doors.DoorStatus
} into g2
select new
{
BuildingCode = g2.Key.BuildingCode,
DoorID = g2.Key.DoorID,
Status = g2.Key.DoorStatus
NumOpenings = g2.Sum(i => (i == null ? 0 : i.Opening)),
NumClosings = g2.Sum(i => (i == null ? 0 : i.Closing))
};