2010-04-06 7 views
6

J'ai créé deux entités (simplifié) en C#:LINQ: affichage des résultats des listes vides

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

J'utilise le code suivant pour initialiser les objets:

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

La méthode ci-dessous est utilisé pour obtenir les journaux de date:

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

le résultat de la requête LINQ ci-dessus est: Ma question est, quelle est la meilleure façon de réécrire la requête LINQ ci-dessus pour inclure les résultats du deuxième objet que j'ai créé (Log2), car il a une liste vide. En d'autres termes, je voudrais afficher toutes les dates même si elles n'ont pas de valeurs temporelles.

Le résultat attendu serait:

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

Vous avez besoin de publier la fonction 'executeQuery' ... puisque c'est là que toutes les choses importantes se passent ici. –

+0

Y at-il un lien entre les entrées et les journaux? – Nix

Répondre

10

Essayez ceci:

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

Voir la docs for DefaultIfEmpty pour plus d'informations à ce sujet.

EDIT: Vous pouvez simplement changer pour effectuer la dernière partie en mémoire:

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, je reçois ce qui suit avec votre exemple: Impossible d'affecter à la propriété de type anonyme –

+0

Relatif à la première tentative avec ClockIn –

+0

Il semble faire de cet exemple de travail que vous devez convertir en un type Nullable, et dans ce cas, j'ai posté un Exemple de conversion en (DateTime?). Je ne savais pas que vous ne pouviez pas attribuer une valeur null à une propriété de type anonyme. –

3

Ceci est construit au-dessus de la solution de Jon. En utilisant ce que je reçois l'erreur suivante:

Cannot assign to anonymous type property

J'ai mis à jour l'exemple de Jon à ce qui suit et il semble donner le résultat souhaité:

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

post-scriptum le .Dump() est dû à moi en utilisant LINQ Pad.

+0

merci par la réponse, cela a fonctionné parfaitement! –

Questions connexes