Почему в LINQ предложение Where выполняется после GroupBy? - PullRequest
0 голосов
/ 08 февраля 2019

В приложении C # в .NET Core, которое управляет процессом аудита в компании, у меня есть два набора данных, Expert и Employee, принадлежащих _context.

  • Employee относится ко всем сотрудникам компании, поэтому они получили идентификатор компании CidEmployee может быть несколько записей с одним и тем же Cid, но срок действия записи устанавливается через интервал StartDate - EndDate.
  • Expert может относиться как к Employee(Internal флаг установлен на true) и люди, внешние по отношению к компании, поэтому не все записи в Expert имеют Cid.Не каждый Employee является Expert.

Набор данных моделируется следующим образом:

class Employee{
    public int Cid { get; set;}
    public string Name { get; set;}
    public string Surname { get; set;}
    public string Address { get; set;}
    public DateTime StartDate{ get; set;}
    public DateTime EndDate{ get; set;}
}

class Expert{
    public int Id { get; set;}
    public bool Internal { get; set;}
    public int Cid { get; set;}
}

Я хотел бы получить список со всеми Expertsи для тех Internal я хотел бы получить также Name, Surname и Address с самым высоким EndDate.

Первый шаг - left join между Expert иEmployee:

var experts = from exp in _context.Expert
              join emp in _context.Employee
              on exp.Cid equals emp.Cid into experts
              from expertsDetail in experts.DefaultIfEmpty()
              select new 
              {
                  emp.Cid,
                  emp.Name,
                  emp.Surname,
                  emp.Address,
                  emp.StartDate,
                  emp.EndDate,
                  exp.Internal
              };

Затем я фильтрую только те записи, которые Internal, а затем группирую по Cid.Затем в любой группе я нахожу максимальную дату для выбора правильной записи Internal в пределах experts

Dictionary<string, DateTime> expertsByCid = experts.Where(e => e.Internal)
                                                   .GroupBy(e => e.Cid)
                                                   .ToDictionary(e => e.Key, e => e.Max(t => t.EndDate));

experts.Where(e => e.Internal ? e.EndDate == expertsByCid[e.Cid] : true);

Первая инструкция из приведенного выше кода выдает NullReferenceException.То же самое относится и к этому:

Dictionary<string, DateTime> expertsByCid = (from expert in (from expert in experts where expert.Internal select expert)
group expert by expert.Cid).ToDictionary(e => e.Key, e => e.Max(t => t.EndDate));

Вместо этого, если я использую это:

Dictionary<string, DateTime> expertsByCid = experts.Where(e => e.Internal)
                                                   .ToList()
                                                   .GroupBy(e => e.Cid)
                                                   .ToDictionary(e => e.Key, e => e.Max(t => t.EndDate));

, код выполняется без проблем, и я получаю ожидаемый результат.Вероятно, в первой версии, когда LINQ переводит запрос в SQL, предложение WHERE выполняется после GROUPBY, и поэтому оно группирует также записи, которые не являются Internal, где Cid равно null.

Я попытался проверить выполненный SQL, включив соответствующий уровень журнала (я использую .NET Core), но, поскольку он выдает исключение, он не показывает созданный запрос.

Хотя это объяснение кажется немного нелогичным, есть кто-нибудь еще лучше?

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