2015-03-17 4 views
0

Я пытаюсь создать запрос, показывающий эффективность по отделам, а затем и месяц. Мне нужно, чтобы каждый месяц включался, даже если в этом месяце нет данных.Left Outer Join with Multiple Conditions - Null Exception

Первый запрос для получения данных отлично работает, как и простой запрос, чтобы получить последние двенадцать месяцев.

Однако, когда я пытаюсь закрыть внешнее соединение, я получаю исключение null, хотя я обрабатываю каждое поле, которое является нулевым в select new.

Я не могу видеть, где я неправильно ...

var departmentMonthlyEfficiences = 
    (from o in operations 
    join contract in contracts on o.Contract equals contract.Sequence.ToString() 
    group o by new { o.Department, o.LastWorkDate.Year, o.LastWorkDate.Month} into dm 
    where dm.Sum(o => o.ActualHours) > 0 
    select new { Department = dm.Key.Department, Year = dm.Key.Year, Month = dm.Key.Month, Efficiency = dm.Sum(o => o.PlannedHours)/dm.Sum(o => o.ActualHours) }); 

var now = DateTime.Now; 
var months = Enumerable.Range(-12, 12) 
    .Select(x => new { 
     Year = now.AddMonths(x).Year, 
     Month = now.AddMonths(x).Month }); 

var departmentAllMonthlyEfficiences = (
     from m in months 
     join deptMonth in departmentMonthlyEfficiences on new { Month = m.Month, Year = m.Month } equals new { Month = deptMonth.Month, Year = deptMonth.Year } into deptsWithAllMonths 
     from deptAllMonth in deptsWithAllMonths.DefaultIfEmpty() 

     select new { 
     Department= deptAllMonth.Department == null ? "empty": deptAllMonth.Department, 
     Year=m.Year == null ? 2019: m.Year, 
     Month=m.Month == null ? 12:m.Month, 
     Efficiency=deptAllMonth.Efficiency == null ? 0: deptAllMonth.Efficiency 
     }).ToList(); 

ответ

0

Ключевое слово join (обычно внутреннее соединение) вместе с методом расширения DefaultIfEmpty подражают в LINQ внешнее соединение (и LINQ к -Entities сделает это так, когда генерируется фактический SQL). DefaultIfEmpty говорит, что — должен deptsWithAllMonths быть пустое множество — возвращать множество, содержащее один, по умолчанию, объект вместо ... объекта по умолчанию для анонимного типа возвращаемого из первого запроса null:

select new 
{ 
    Department = deptAllMonth == null || deptAllMonth.Department == null 
        ? "empty" 
        : deptAllMonth.Department, 
    Year = m.Year, 
    Month = m.Month, 
    Efficiency = deptAllMonth == null || deptAllMonth.Efficiency == null 
        ? 0 
        : deptAllMonth.Efficiency 
} 

Однако, вам следует рассмотреть этот совет: Navigation Properties are More Readable than Joins. Один из важных аспектов использования навигационных свойств применяется в случае вашего вопроса:

LINQ to SQL и LINQ to Entities объединяются с нулями.