c# - Comment exprimer le plus élégamment la jointure gauche avec SQL agrégé en tant que requête LINQ

Translate

SQL:

SELECT
   u.id,
   u.name,
   isnull(MAX(h.dateCol), '1900-01-01') dateColWithDefault
FROM universe u
LEFT JOIN history h 
   ON u.id=h.id 
   AND h.dateCol<GETDATE()-1
GROUP BY u.Id, u.name
This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Une solution, même si elle diffère la gestion de la valeur nulle au code, pourrait être:

DateTime hier = DateHeure.Now.Date.AddDays (-1);

var collection=
    from u in db.Universe
    select new
    {
        u.id,
        u.name,
        MaxDate =(DateTime?)
       (
           from h in db.History
           where u.Id == h.Id
           && h.dateCol < yesterday
           select h.dateCol 
       ).Max()
    };

Cela ne produit pas exactement le même SQL, mais fournit le même résultat logique. Traduire des requêtes SQL «complexes» en LINQ n'est pas toujours simple.

La source
Hyman Lee
Translate
var collection=
    from u in db.Universe
    select new
    {
        u.id,
        u.name,
        MaxDate =(DateTime?)
       (
           from h in db.History
           where u.Id == h.Id
           && h.dateCol < yesterday
           select h.dateCol 
       ).Max()
    };

Utilisez simplement le code ci-dessus et cela devrait fonctionner correctement!

La source
Translate

Ce n'est pas une réponse complète pour vous, mais sur la pièce de jointure de gauche, vous pouvez utiliser l'opérateur DefaultIfEmpty comme suit:

var collection = 
from u in db.Universe
join history in db.History on u.id = history.id into temp
from h in temp.DefaultIfEmpty()
where h.dateCol < DateTime.Now.Date.AddDays(-1)
select u.id, u.name, h.dateCol ?? '1900-01-01'

Je n'ai pas encore eu besoin de faire de commandes groupby, alors j'ai laissé cela de côté pour ne pas vous envoyer sur le mauvais chemin. Deux autres choses rapides à noter. Je n'ai pas pu réellement joindre sur deux paramètres bien que comme ci-dessus il existe des moyens de le contourner. Également ?? L'opérateur fonctionne très bien à la place de isnull dans SQL.

La source
Translate

Vous allez vouloir utiliser lejoin intoconstruct pour créer une requête de groupe.

TestContext db = new TestContext(CreateSparqlTripleStore());
var q = from a in db.Album
        join t in db.Track on a.Name equals t.AlbumName into tracks
        select new Album{Name = a.Name, Tracks = tracks};
foreach(var album in q){
    Console.WriteLine(album.Name);
    foreach (Track track in album.Tracks)
    {
        Console.WriteLine(track.Title);
    }
}
La source