我正在升级到EF Core 3.0和.NET Core 3.0,但是我的某些查询停止了工作。这是一个示例:
我有一个名为Bins
的表,还有另一个名为BinItems
的表,现在它当然具有一对多的关系。 BinItems
有一个名为Qty
的属性,我想根据客户端在过滤器中给出的条件来总结Qty
中的所有BinItems
。
下面是代码:
var query = _binRepository.Table;
if (filter.LastRecountDate != null) {
query = query.Where(x => x.LastRecountDate.Date == filter.LastRecountDate.Value.Date);
}
if (filter.StartRecountDate != null) {
query = query.Where(x => x.LastRecountDate.Date >= filter.StartRecountDate.Value.Date);
}
if (filter.EndRecountDate != null) {
query = query.Where(x => x.LastRecountDate.Date <= filter.EndRecountDate.Value.Date);
}
if (filter.Active != null) {
query = query.Where(x => x.Active == filter.Active);
}
if (!string.IsNullOrEmpty(filter.BinLocation)) {
query = query.Where(x => x.BinLocation == filter.BinLocation);
}
if (!string.IsNullOrEmpty(filter.Gtin)) {
query = query.Where(x => x.BinItems.Any(o => o.UPC == filter.Gtin));
}
if (filter.WarehouseIds.Count() > 0) {
query = query.Where(x => filter.WarehouseIds.Contains(x.Zone.Id));
}
if (!string.IsNullOrEmpty(filter.Keywords)) {
query = query.Where(x => x.BinItems.Select(o => o.UPC).Contains(filter.Keywords));
}
query = query.Include(x => x.BinItems).Include(x => x.Zone);
if (!string.IsNullOrEmpty(filter.Keywords)) {
return await query.SumAsync(x => x.BinItems.Where(p => p.UPC.Contains(filter.Keywords)).Sum(o => o.Qty));
}
return await query.SumAsync(x => x.BinItems.Sum(o => o.Qty));
我抛出异常:
Microsoft.Data.SqlClient.SqlException(0x80131904):无法执行 包含聚合或 子查询。
它在.NET Core 2.1和EF Core 2中完全可以正常工作,但是现在我在所有以这种方式进行的查询中都遇到这些错误。
有人知道如何在.NET Core 3.0 / EF Core 2中获得这项工作吗?
答案 0 :(得分:2)
问题是嵌套聚合(在这种情况下,是Sum
中的Sum
)。 EF Core 3.0仍然无法正确转换此类聚合。它最有可能在3.0之前的版本中与客户评估一起使用,而该评估已在3.0中删除。
解决方案与往常一样,是避免嵌套聚合,并在扁平化(通过SelectMany
)集上执行单个聚合。它适用于Average
以外的所有标准分组聚合。
这是该查询的解决方案(请注意,Include
不必要,因为查询是在服务器端执行的):
var query = _binRepository.Table;
// ... (query filters)
var innerQuery = query.SelectMany(x => x.BinItems);
if (!string.IsNullOrEmpty(filter.Keywords)) {
innerQuery = innerQuery.Where(x => x.UPC.Contains(filter.Keywords));
}
return await innerQuery.SumAsync(x => x.Qty);