Запрос Linq: внутреннее объединение с группой count () по подзапросу - PullRequest
0 голосов
/ 27 января 2019

У нас есть несколько машин с подключенными устройствами.Не на всех машинах установлены устройства, и устройства можно перемещать между машинами.Устройства генерируют ошибки, и нам нужно сосчитать эти ошибки, произошедшие за прошедший день.

У нас есть четыре таблицы: машины (с Id и кодом), устройства (с Id и кодом), таблица сопряжения DevicesMachines (Id, IdMachine, IdDevice, From datetime, To datetime) и ошибки (Id, IdDevice, Moment datetime, Description).

Рабочий запрос SQL выглядит так:

Select m.Id, m.Code, 
   Coalesce(d.Code, 'NA') As DeviceCode,
   Coalesce(Err.ErrorCnt,0) As ErrorCnt
From Machines As m
Left Outer Join (Select IdMachine, IdDevice From DevicesMachines as dm 
Where GetDate() Between dm.From And dm.To) As dm on m.Id=dm.IdMachine
Left Outer Join Devices As d on dm.IdDevice=d.Id
Left outer join 
  ( Select IdMachine, Count(Id) As ErrorCnt From Errors as er 
    Where er.Moment >= DateAdd(day,-1,GetUtcDate()) 
    Group By IdMachine) As Err 
On m.Id=Err.IdMachine

Я пробовал многосинтаксис, один из которых приведен ниже:

using ( DataContextM dcMachines = new dataContextM())
{
  IEnumerable<MachineRow> lstM = 
    from m in dcMachines.Machines
    from dm in dcMachines.DevicesMachines.Where(dm => (dm.IdMachine == m.Id) && (dm.From <= DateTime.Now) && (dm.To >= DateTime.Now)).DefaultIfEmpty()
    from d in dcMachines.Devices.Where(d => d.Id == dm.IdDevice).DefaultIfEmpty()
    from er in dcMachines.Errors
        .Where(er => (er.Moment >= DateTime.Now) && (er.Moment <= DateTime.Now.AddDays(-1))) 
        .GroupBy(er => er.IdMachine)
        .Select(er => new { IdMachine = er.Key, ErrorCnt = er.Count() })
        .Where(er=> er.IdMachine==m.Id).DefaultIfEmpty()
 select new MachineRow
 {
    Id = amId,
    Code = m.Code,
    DeviceCode = (d == null) ? "NA" : d.DeviceCode,
    IdDevice = (d == null) ? 0: d.Id,
    ErrorCnt = (er == null) ? 0 : er.ErrorCnt
  };
}

Мне не удалось найти правильный синтаксис Linq, и мне нужна ваша помощь.

Спасибо, Даниэль

1 Ответ

0 голосов
/ 28 января 2019

На основе предоставленного вами SQL я создал то, что я считаю эквивалентным выражению EF LINQ:

using (var dcMachines = new DataContextM())
{
    var now = DateTime.Now;
    var utcYesterday = DateTime.UtcNow.AddDays(-1);

    var devicesMachinesQuery =
        from dm in dcMachines.DevicesMachines
        where dm.From <= now && dm.To >= now
        join d in dcMachines.Devices on dm.IdDevice equals d.Id into dItems
        from d in dItems.DefaultIfEmpty()
        select new
        {
            dm.IdMachine,
            dm.IdDevice,
            DeviceCode = d != null ? d.Code : "NA"
        };

    var errorsQuery =
        from err in dcMachines.Errors
        where err.Moment >= utcYesterday
        select err;

    IEnumerable<MachineRow> lstM =
        from m in dcMachines.Machines
        join dm in devicesMachinesQuery on m.Id equals dm.IdMachine into dmItems
        from dm in dmItems.DefaultIfEmpty()
        select new MachineRow
        {
            Id = m.Id,
            Code = m.Code,
            DeviceCode = dm != null ? dm.DeviceCode : "NA",
            IdDevice = dm != null ? dm.IdDevice : 0,
            ErrorCnt = (
                from err in errorsQuery
                where err.IdMachine == m.Id
                select err.Id
                )
                .Count()
        };
}

Я провел несколько тестов в памяти, и, похоже, он работает так же, как и ваш SQL-запрос.

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