单个LINQ查询中的多个总和会触发多个SQL查询

时间:2018-06-07 11:37:09

标签: c# linq

作为一个简单的例子,我们假设我们有一个名为“myQueryable”的IQueryable,包含3列Id,Value1和Value2,我们编写以下LINQ表达式:

var result = myQueryable.Select(g => new 
{ 
    Value1Sum = g.Sum(b => b.Value1),
    Value2Sum = g.Sum(b => b.Value2)                                  
});

这将触发2个不同的查询,每个查询一个,然后将它们作为像

之类的对象返回
{ Value1Sum = x , Value2Sum = y }

是否可以以这样的方式构建LINQ表达式,即只为两个总和触发一个查询?毕竟它们都是基于相同的数据集来计算的。

为了更清楚,我希望这样的查询:

SELECT SUM(Value1), SUM(Value2) FROM MyTable

但LINQ会生成两个这样的查询(出于安全原因无法发布实际查询):

exec sp_executesql N'SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    SUM([Extent1].[Value1]) AS [A1]
    FROM [mo].[MyTable] AS [Extent1]) AS [GroupBy1]

..同样适用于Value2。请注意,即使它调用内部选择“GroupBy1”,也没有任何分组(也在实际查询中)

1 个答案:

答案 0 :(得分:2)

是的,您可以在对数据库的单个查询中执行此操作。

首先,获取所需的所有值。

ddepth=-1

使用var values = MyQueryable.Select(item => new { Value1 = item.Value1 , Value2 = item.Value2 }) .ToList(); 强制查询执行。 ToList()仅用于最小化您查询的数据。你也可以使用

Select()

这是您唯一的数据库之旅。

现在您已在本地拥有所有数据,您可以聚合这些值。

var values = MyQueryable.ToList();

之后您有一个元组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)); ,其中sums代表所有sums.Item1的总和,Value1分别代表所有sums.Item2的总和。

我可以直接在Value2上使用Aggregate吗?

不幸的是,没有。 IQueryable<T> is not supported in LINQ to Entities,因此无法直接在Aggregate()上使用它。这就是您首先需要在本地获取数据以便拥有IQueryable<T>的原因。 然后您可以使用 LINQ to objects 来聚合结果。有关两者之间的区别,请参阅this StackOverflow answer