Considera la seguente query che deve restituire un regista insieme ai conteggi di film e attori per ciascun film. Come si potrebbe scrivere questo in LINQ usando EF CORE 2.2? Ho bisogno del LINQ per generare SQL che utilizza effettivamente GROUP BY con gli aggregati SQL supportati in EF CORE 2.1 e forward.
SELECT DirectorName, COUNT(m.MovieID), COUNT(a.ActorID)
FROM Directors d
LEFT OUTER JOIN Movies AS m ON m.DirectorID = d.DirectorID
LEFT OUTER JOIN Actors AS a ON a.MovieID = m.MovieID
WHERE d.DirectorID = 1
GROUP BY DirectorName
La query LINQ di esempio è stata creata in base a una risposta e mi fornisce risultati, ma la query ha solo uno dei join LEFT e nessun gruppo di. L'output indica che DefaultIfEmpty (), GroupBy e Count non possono essere tradotti e verranno valutati localmente.
var results =
(
from d in _moviesContext.Directors
join m in _moviesContext.Movies on d.DirectorId equals m.DirectorId
into grpM from movies in grpM.DefaultIfEmpty()
join a in _moviesContext.Actors on movies.MovieId equals a.MovieId
into grpA from actors in grpA.DefaultIfEmpty()
where d.DirectorId == 1
group new { d, grpM, grpA } by new
{
d.DirectorName
} into grp
select new
{
DirectoryName = grp.Key.DirectorName,
MovieCount = grp.Sum(g => g.grpM.Count()),
ActorAcount = grp.Sum(g => g.grpA.Count())
}
).ToList();
L'espressione LINQ 'DefaultIfEmpty ()' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'DefaultIfEmpty ()' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'dei film di film in {[grpM] => DefaultIfEmpty ()}' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Avviso: l'espressione LINQ 'GroupBy (nuovo <> f__AnonymousType8
1(DirectorName = [d].DirectorName), new <>f__AnonymousType6
2 (d = [d], grpM = [grpM]))' potrebbe non essere tradotto e verrà valutato localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'DefaultIfEmpty ()' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'DefaultIfEmpty ()' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'dei film di film in {[grpM] => DefaultIfEmpty ()}' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Avviso: l'espressione LINQ 'GroupBy (nuovo <> f__AnonymousType81(DirectorName = [d].DirectorName), new <>f__AnonymousType6
2 (d = [d], grpM = [grpM]))' potrebbe non essere tradotto e verrà valutato localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'Count ()' non può essere tradotta e verrà valutata localmente. Microsoft.EntityFrameworkCore.Query: Attenzione: l'espressione LINQ 'Sum ()' non può essere tradotta e verrà valutata localmente.
Ecco i modelli
public partial class Directors
{
public int DirectorId { get; set; }
public string DirectorName { get; set; }
}
public partial class Movies
{
public int MovieId { get; set; }
public string MovieName { get; set; }
public int? DirectorId { get; set; }
}
public partial class Actors
{
public int ActorId { get; set; }
public string ActorName { get; set; }
public int? MovieId { get; set; }
}
Non sono sicuro del motivo per cui i tuoi attori hanno solo un'int per Id film quando un attore di solito ha un elenco di film, ma credo che tu abbia bisogno di includere tutti e tre i tipi di oggetti nel tuo gruppo e quindi selezionare film distinti e attori distinti per ottenere i conteggi .
Esempio:
var directors = new[] { new { DirectorName = "Director A", DirectorID = 1 },
new { DirectorName = "Director B", DirectorID = 2 }};
var movies = new[] { new { MovieName = "Movie A", MovieID = 1, DirectorID = 1 },
new { MovieName = "Movie B", MovieID = 2, DirectorID = 2 }};
var actors = new[] { new { ActorName = "Actor A", ActorID = 1, MovieID = 1},
new { ActorName = "Actor B", ActorID = 2, MovieID = 1},
new { ActorName = "Actor C", ActorID = 3, MovieID = 1},
new { ActorName = "Actor D", ActorID = 4, MovieID = 2}};
var results = from d in directors
from m in movies
.Where(m => m.DirectorID == d.DirectorID)
from a in actors
.Where(a => a.MovieID == m.MovieID)
where d.DirectorID == 1
group new { d, m, a } by d.DirectorName into grp
select new
{ DirectorName = grp.Key,
MovieCount = grp.Select(x => x.m).Distinct().Count(),
ActorCount = grp.Select(x => x.a).Distinct().Count()
};
Cederà
result = new [] { new { DirectorName = "Director A", MovieCount = 1, ActorCount = 3}};