2010-04-06 2 views
6

я создал два объекта (упрощенный) в C#:LINQ: отображение результатов из пустых списков

class Log { 
    entries = new List<Entry>(); 

    DateTime Date { get; set; } 
    IList<Entry> entries { get; set; } 
} 

class Entry { 
    DateTime ClockIn { get; set; } 
    DateTime ClockOut { get; set; } 
} 

Я использую следующий код для инициализации объектов:

Log log1 = new Log() { 
    Date = new DateTime(2010, 1, 1),     
}; 
log1.Entries.Add(new Entry() { 
    ClockIn = new DateTime(0001, 1, 1, 9, 0, 0), 
    ClockOut = new DateTime(0001, 1, 1, 12, 0, 0) 
}); 

Log log2 = new Log() 
{ 
    Date = new DateTime(2010, 2, 1), 
}; 

Метод ниже используется для получения журналов Дата:

var query = 
    from l in DB.GetLogs() 
    from e in l.Entries 
    orderby l.Date ascending 
    select new 
    { 
     Date = l.Date, 
     ClockIn = e.ClockIn, 
     ClockOut = e.ClockOut, 
    }; 

результат вышеупомянутого запроса LINQ является:

/* 
Date  | Clock In | Clock Out 
01/01/2010 | 09:00  | 12:00  
*/ 

Мой вопрос: как лучше всего переписать запрос LINQ выше, чтобы включить результаты второго объекта, созданного мной (Log2), поскольку он имеет пустой список. Другими словами, я хотел бы отображать все даты, даже если у них нет значений времени.

Ожидаемый результат будет:

/* 
Date  | Clock In | Clock Out 
01/01/2010 | 09:00  | 12:00  
02/01/2010 |   |    
*/ 
+0

Вам нужно отправить функцию 'executeQuery' ..., так как здесь все важные вещи происходят. –

+0

Есть ли связь между Записями и журналами? – Nix

ответ

10

Попробуйте это:

var query = 
    from l in DB.GetLogs() 
    from e in l.Entries.DefaultIfEmpty() 
    orderby l.Date ascending 
    select new 
    { 
     Date = l.Date, 
     ClockIn = e == null ? null : e.ClockIn, 
     ClockOut = e == null ? null : e.ClockOut, 
    }; 

Смотрите docs for DefaultIfEmpty для получения дополнительной информации о нем.

EDIT: Вы можете просто изменить его, чтобы выполнить заключительную часть памяти:

var dbQuery = 
    from l in DB.GetLogs() 
    from e in l.Entries.DefaultIfEmpty() 
    orderby l.Date ascending 
    select new { Date = l.Date, Entry = e }; 

var query = dbQuery.AsEnumerable() 
        .Select(x => new { 
         Date = x.Date, 
         ClockIn = x.Entry == null ? null : x.Entry.CLockIn, 
         ClockOut = x.Entry == null ? null : x.Entry.CLockOut 
        }); 
+0

Jon, я получаю следующее с вашим примером: Не удается присвоить анонимному типу свойства –

+0

Относительно первой попытки с ClockIn –

+0

Кажется, что этот пример работы вы должны применить к типу с нулевым значением, и в этом случае я опубликовал пример кастинга (DateTime?). Я не знал, что вы не можете назначить null для свойства анонимного типа. –

3

Это строит на вершине решения Джона. С его помощью я получаю следующее сообщение об ошибке:

Cannot assign to anonymous type property

Я обновленный пример Джона к следующему, и, как представляется, дать искомый результат

var logs = new []{log1,log2}; 

var query = 
from l in logs.DefaultIfEmpty() 
from e in l.entries.DefaultIfEmpty() 
orderby l.Date ascending 
select new 
{ 
    Date = l.Date, 
    ClockIn = e == null ? (DateTime?)null : e.ClockIn, 
    ClockOut = e == null ? (DateTime?)null : e.ClockOut, 
}; 

query.Dump(); 

Andrew

P.S. .Dump() из-за меня использует LINQ Pad.

+0

спасибо, ответ он отлично работал! –

Смежные вопросы