As a simple example let's assume we have an IQueryable named "myQueryable" with 3 columns Id, Value1 and Value2 and we write the following LINQ expression:
var result = myQueryable.Select(g => new
{
Value1Sum = g.Sum(b => b.Value1),
Value2Sum = g.Sum(b => b.Value2)
});
This will fire 2 different queries, one for each sum and then return both of them as an object like
{ Value1Sum = x , Value2Sum = y }
Is it possible to build the LINQ Expression in such a way that only one query is fired for both sums? After all they are both calculated on the basis of the same dataset..
To make it clearer, I'd expect a query like this:
SELECT SUM(Value1), SUM(Value2) FROM MyTable
but LINQ generates two queries like this(can't post the actual queries fired for security reasons):
exec sp_executesql N'SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
SUM([Extent1].[Value1]) AS [A1]
FROM [mo].[MyTable] AS [Extent1]) AS [GroupBy1]
..same for Value2. Please note that even if it calls the inner select "GroupBy1" there is no grouping anywhere (also in the actual queries)
First, get all the values you need.
var values = MyQueryable.Select(item => new { Value1 = item.Value1 , Value2 = item.Value2 })
.ToList();
You use ToList()
to force the query to execute. The Select()
is only to minimize the data you query. You might as well use
var values = MyQueryable.ToList();
This is your only trip to the database.
Now that you have all data locally, you can aggregate these values.
Tuple<int, int> sums = values.Aggregate(
new Tuple<int, int>(0,0),
(tuple, item) => new Tuple<int, int>(tuple.Item1 + item.Value1, tuple.Item2 + item.Value2));
Afterwards you have a tuple sums
where sums.Item1
represents the sum of all Value1
and sums.Item2
represents the sum of all Value2
respectively.
Aggregate
directly on my IQueryable<T>
?Unfortunately, no. Aggregate()
is not supported in LINQ to Entities, so you cannot use it on IQueryable<T>
directly. This is why you first need to get the data locally so you have an IEnumerable<T>
. Then you can aggregate the results using LINQ to objects. See this StackOverflow answer on the distinction between the two.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With