EF Core 3.0 SumAsync触发聚合函数异常

时间:2019-11-14 16:28:37

标签: c# asp.net-core entity-framework-core asp.net-core-3.0 ef-core-3.0

我正在升级到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中获得这项工作吗?

1 个答案:

答案 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);