¿Cómo puedo más elegante de expresar left join con agregado de SQL como de consulta de LINQ
Pregunta
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
Solución
Una solución, aunque sea uno que difiere de la manipulación del valor nulo para el código, podría ser:
DateTime ayer = DateTime.Ahora.Fecha.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()
};
Esto no producen exactamente el mismo SQL, pero no proporciona el mismo resultado lógico.La traducción de "complejo" de SQL consultas de LINQ no siempre es sencillo.
Otros consejos
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()
};
Sólo youse el código anterior y esto debería funcionar bien!
Esto no es una respuesta completa para usted, pero en el left join pieza puede utilizar el defaultifempty junto operador así:
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'
No he tenido la necesidad de hacer cualquier groupby comandos sin embargo, así que dejó que fuera como para no llevarte por el mal camino.Otras dos cosas rápidas para nota.He sido incapaz de vincularse en dos parámetros, aunque como en el anterior, hay maneras de conseguir alrededor de él.También, el ??operador que funciona realmente bien en lugar de la isnull en SQL.
Usted va a querer usar el join into
construir para crear una consulta de grupo.
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);
}
}