我有以下查询,我期待一些结果。但我只得到一个结果。
var results = await DbContext.Trucks
.Where(t => t.Departure.HasValue)
.Select(t => new
{
t.Departure!.Value.Year,
t.Departure!.Value.Month,
Quantity = t.InboundQuantity + t.ToTransfers.Sum(x => x.Quantity) - t.FromTransfers.Sum(x => x.Quantity)
})
.GroupBy(t => new { t.Year, t.Month })
.ToDictionaryAsync(g => new DateTime(g.Key.Year, g.Key.Month, 1), g => g.Sum(x => x.Quantity));
结果
results Count = 1
+ [0] {[{7/1/2021 12:00:00 AM}, 3842405714]}
如果我重写查询以将所有行加载到内存中然后进行分组,那么我就会得到预期数量的结果。
var test = DbContext.Trucks
.Where(t => t.Departure.HasValue)
.Select(t => new
{
t.Departure!.Value.Year,
t.Departure!.Value.Month,
Quantity = t.InboundQuantity + t.ToTransfers.Sum(x => x.Quantity) - t.FromTransfers.Sum(x => x.Quantity)
})
.ToList();
var test2 = test
.GroupBy(t => new { t.Year, t.Month })
.ToDictionary(g => new DateTime(g.Key.Year, g.Key.Month, 1), g => g.Sum(x => x.Quantity));
结果
test2 Count = 27
+ [0] {[{1/1/2022 12:00:00 AM}, 95309170]}
+ [1] {[{2/1/2022 12:00:00 AM}, 79737674]}
+ [2] {[{3/1/2022 12:00:00 AM}, 173875538]}
+ [3] {[{7/1/2021 12:00:00 AM}, 125219196]}
+ [4] {[{8/1/2021 12:00:00 AM}, 110993954]}
+ [5] {[{10/1/2021 12:00:00 AM}, 129282632]}
+ [6] {[{11/1/2021 12:00:00 AM}, 160927222]}
+ [7] {[{12/1/2021 12:00:00 AM}, 117813444]}
+ [8] {[{9/1/2021 12:00:00 AM}, 26260420]}
+ [9] {[{4/1/2022 12:00:00 AM}, 161695966]}
+ [10] {[{5/1/2022 12:00:00 AM}, 184781001]}
+ [11] {[{6/1/2022 12:00:00 AM}, 146985217]}
+ [12] {[{7/1/2022 12:00:00 AM}, 84260160]}
+ [13] {[{8/1/2022 12:00:00 AM}, 89769875]}
+ [14] {[{10/1/2022 12:00:00 AM}, 187958697]}
+ [15] {[{11/1/2022 12:00:00 AM}, 175034225]}
+ [16] {[{9/1/2022 12:00:00 AM}, 108421771]}
+ [17] {[{1/1/2023 12:00:00 AM}, 179720773]}
+ [18] {[{12/1/2022 12:00:00 AM}, 110000415]}
+ [19] {[{2/1/2023 12:00:00 AM}, 210461751]}
+ [20] {[{3/1/2023 12:00:00 AM}, 232239876]}
+ [21] {[{4/1/2023 12:00:00 AM}, 176482465]}
+ [22] {[{5/1/2023 12:00:00 AM}, 218732769]}
+ [23] {[{6/1/2023 12:00:00 AM}, 186324324]}
+ [24] {[{7/1/2023 12:00:00 AM}, 151700649]}
+ [25] {[{8/1/2023 12:00:00 AM}, 142653374]}
+ [26] {[{9/1/2023 12:00:00 AM}, 75763156]}
我可能在这里遗漏了一些愚蠢的东西,但我无法解释这一点。
为什么第一个查询没有按预期工作?
分组没有聚合就没有降神会,
ToDictionaryAsync
试图在客户端枚举IGrouping<,>
。在调用 Select
之前添加额外的 ToDictionaryAsync
:
var results = await DbContext.Trucks
.Where(t => t.Departure.HasValue)
.Select(t => new
{
t.Departure!.Value.Year,
t.Departure!.Value.Month,
Quantity = t.InboundQuantity + t.ToTransfers.Sum(x => x.Quantity) - t.FromTransfers.Sum(x => x.Quantity)
})
.GroupBy(t => new { t.Year, t.Month })
.Select(g = new
{
g.Key.Year,
g.Key.Month,
Quantity = g => g.Sum(x => x.Quantity)
})
.ToDictionaryAsync(x => new DateTime(x.Year, x.Month, 1), g => x.Quantity);
更新,由于这里我们有 EF Core SQL 生成限制,准备了解决方法:
var trucks = DbContext.Trucks
.Where(t => t.Departure.HasValue);
var toSummary =
from t in trucks
from tr in t.ToTransfers
group tr by new
{
t.Departure!.Value.Year,
t.Departure!.Value.Month,
} into g
select new
{
g.Key.Year,
g.Key.Month,
ToQuantity = g.Sum(x => x.Quantity)
};
var fromSummary =
from t in trucks
from tr in t.FromTransfers
group tr by new
{
t.Departure!.Value.Year,
t.Departure!.Value.Month,
} into g
select new
{
g.Key.Year,
g.Key.Month,
FromQuantity = g.Sum(x => x.Quantity)
};
var query =
from t in trucks
from to in toSummary
.Where(to => t.Year == t.Departure!.Value.Year && t.Month == t.Departure!.Value.Month)
.DefaultIfEmpty()
from f in fromSummary
.Where(f => f.Year == t.Departure!.Value.Year && f.Month == t.Departure!.Value.Month)
.DefaultIfEmpty()
select new
{
g.Key.Year,
g.Key.Month,
Quantity = t.InboundQuantity + ((int?)to.ToQuantity) ?? 0 - ((int?)f.FromQuantity) ?? 0
}
var results = await query
.ToDictionaryAsync(x => new DateTime(x.Year, x.Month, 1), g => x.Quantity);