2010-04-06 16 views
6

ich zwei Entitäten erstellt haben (vereinfacht) in C#:LINQ: Anzeige ergibt sich aus leeren Listen

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; } 
} 

ich den folgenden Code verwende die Objekte zu initialisieren:

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), 
}; 

Verfahren unter wird verwendet, um die Datum-Protokolle zu erhalten:

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, 
    }; 

Das Ergebnis der oben LINQ-Abfrage ist:

Meine Frage ist, was ist die beste Möglichkeit, die obige LINQ-Abfrage neu zu schreiben, um die Ergebnisse aus dem zweiten Objekt, das ich erstellt habe (Log2), aufzunehmen, da es eine leere Liste hat. Mit anderen Worten, ich möchte alle Daten anzeigen, auch wenn sie keine Zeitwerte haben.

würde das erwartete Ergebnis sein: Das

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

Sie müssen die Funktion 'executeQuery' posten, da hier alle wichtigen Dinge passieren. –

+0

Gibt es einen Link zwischen Einträgen und Protokollen? – Nix

Antwort

10

Versuchen:

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, 
    }; 

die docs for DefaultIfEmpty darauf für weitere Informationen.

EDIT: Vielleicht möchten Sie es einfach ändern Sie den letzten Teil im Speicher auszuführen:

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, ich bekomme folgendes mit Ihrem Beispiel: kann nicht an anonymer Eigenschaft zugewiesen werden –

+0

In Bezug auf den ersten Versuch mit ClockIn –

+0

Es scheint dieses Beispiel funktionieren müssen Sie auf einen Nullable-Typ zu werfen, und in diesem Fall habe ich ein Beispiel Casting nach (DateTime?). Ich wusste nicht, dass Sie einer anonymen Eigenschaft keine null zuweisen können. –

3

Dies baut auf der Lösung von Jon. Mit ihm bekomme ich folgende Fehlermeldung:

Cannot assign to anonymous type property

Ich habe Jons Beispiel auf die folgende aktualisiert und es erscheint das gewünschte Ergebnis zu geben:

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. die .Dump() ist wegen mir mit LINQ Pad.

+0

danke von der antwort, es hat perfekt funktioniert! –

Verwandte Themen