I wanted to make a single query (because perhaps we are working on a DB, and each query has a cost "just because it is a query") and do all the computation SQL-side, so that I receive back a single row (because if there are 1000 reviews, I don't really need to download all of them... I want the sum of their MovieRating
and their count).
// Based on https://stackoverflow.com/a/45144198/613130
var result = reviews
.Where(x => x.MovieID == m.MovieID)
.GroupBy(x => 1)
.Select(x => ((double?)x.Sum(y => y.MovieRating)) / x.Count())
.FirstOrDefault() ?? -1.0;
The result
will be -1.0
if there aren't reviews for the MovieID
. Note the use of cast because otherwise we will have an integer division probably (if MovieRating
is an integer).
Note that there won't be any division if a row isn't found (because there won't be any Group
)
The equivalent query on a SQL database should be
SELECT CAST(SUM(x.MovieRating) AS FLOAT) / COUNT(*)
FROM Reviews x
WHERE x.MovieID = @MovieID
GROUP BY 1
But in truth the EF translated it in a much more complex way :-) (tested on EF 6.2.0):
SELECT
CAST( [GroupBy1].[A1] AS float) / CAST( [GroupBy1].[A2] AS float) AS [C1]
FROM ( SELECT
[Filter1].[K1] AS [K1],
SUM([Filter1].[A1]) AS [A1],
COUNT([Filter1].[A2]) AS [A2]
FROM ( SELECT
1 AS [K1],
[Extent1].[MovieRating] AS [A1],
1 AS [A2]
FROM #Reviews AS [Extent1]
WHERE [Extent1].[MovieId] = @p__linq__0
) AS [Filter1]
GROUP BY [K1]
) AS [GroupBy1]