В приложении C # в .NET Core, которое управляет процессом аудита в компании, у меня есть два набора данных, Expert
и Employee
, принадлежащих _context
.
Employee
относится ко всем сотрудникам компании, поэтому они получили идентификатор компании Cid
.В Employee
может быть несколько записей с одним и тем же 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), но, поскольку он выдает исключение, он не показывает созданный запрос.
Хотя это объяснение кажется немного нелогичным, есть кто-нибудь еще лучше?