简体   繁体   English

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

[英]Multiple sums in a single LINQ query fire multiple SQL queries

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: 作为一个简单的例子,我们假设我们有一个名为“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)                                  
});

This will fire 2 different queries, one for each sum and then return both of them as an object like 这将触发2个不同的查询,每个查询一个,然后将它们作为对象返回

{ 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? 是否有可能以这样的方式构建LINQ表达式,即只为两个总和触发一个查询? 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): 但LINQ会生成两个这样的查询(出于安全原因无法发布实际的查询):

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. ..值为Value2。 Please note that even if it calls the inner select "GroupBy1" there is no grouping anywhere (also in the actual queries) 请注意,即使它调用内部选择“GroupBy1”,也没有任何分组(也在实际查询中)

Yes, you can do that in a single query to your database. 是的,您可以在对数据库的单个查询中执行此操作。

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. 您使用ToList()来强制执行查询。 The Select() is only to minimize the data you query. Select()仅用于最小化您查询的数据。 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. 之后你有一个元组sums ,其中sums.Item1代表所有Value1sums.Item2的总和sums.Item2代表所有Value2的总和。

Can I use Aggregate directly on my IQueryable<T> ? 我可以直接在IQueryable<T>上使用Aggregate吗?

Unfortunately, no. 很不幸的是,不行。 Aggregate() is not supported in LINQ to Entities , so you cannot use it on IQueryable<T> directly. LINQ to Entities不支持 Aggregate() ,因此您无法直接在IQueryable<T>上使用它。 This is why you first need to get the data locally so you have an IEnumerable<T> . 这就是您首先需要在本地获取数据以便拥有IEnumerable<T> Then you can aggregate the results using LINQ to objects . 然后,您可以使用LINQ到对象聚合结果。 See this StackOverflow answer on the distinction between the two. 请参阅StackOverflow这两个区别的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM