.NET 7 OData v4 API中$expand内$apply聚合报错的解决咨询
OData v4 聚合关联实体总和时筛选报错的解决方法
问题场景
我正在开发基于.NET 7的API,用OData v4暴露带分期关联的财务记录(FinancialRecords关联Installments)。想要计算每条财务记录的分期金额总和,对比自身Amount字段筛选出已全额付清的记录,但执行查询时报错。
原查询语句
https://localhost:7046/odata/FinancialRecords/?$expand=Installments($apply=aggregate(Amount with sum as Total))&$count=true&$filter=Installments/Total eq Amount and IsDeleted eq false&$orderby=PaidOn desc&$skip=0&$top=12
报错信息
The parent value for a property access of a property 'Total' is not a single value. Property access can only be applied to a single value.
错误原因
$expand里的聚合是针对每条FinancialRecords下的Installments集合计算总和,但$filter中直接访问Installments/Total时,OData判定Installments是集合类型,无法直接引用集合上的聚合结果做筛选——因为$expand的聚合结果仅附着在展开的集合上,不属于父实体的属性,不能作为单个值参与筛选逻辑。
修复方案
提供两种可行解决方式:
方式1:给父实体添加计算属性(推荐)
在FinancialRecord实体中新增计算属性直接返回分期总和,再配置OData模型支持该属性的筛选:
- 修改实体类
public class FinancialRecord { // 原有属性保留 public decimal Amount { get; set; } public bool IsDeleted { get; set; } public DateTime? PaidOn { get; set; } public ICollection<Installment> Installments { get; set; } // 新增计算属性:计算分期总金额 public decimal InstallmentTotal => Installments?.Sum(i => i.Amount) ?? 0; }
- 配置OData模型
在模型构建器中标记该属性为计算属性,允许OData筛选:
builder.EntityType<FinancialRecord>() .Property(f => f.InstallmentTotal) .IsComputed();
- 简化后的查询语句
https://localhost:7046/odata/FinancialRecords/?$count=true&$filter=InstallmentTotal eq Amount and IsDeleted eq false&$orderby=PaidOn desc&$skip=0&$top=12
方式2:在父实体层级使用$apply聚合
如果不想修改实体类,可直接在FinancialRecords实体集上通过groupby聚合计算分期总和,再筛选:
https://localhost:7046/odata/FinancialRecords/?$apply=groupby((Id, Amount, IsDeleted, PaidOn), aggregate(Installments/Amount with sum as InstallmentTotal))&$filter=InstallmentTotal eq Amount and IsDeleted eq false&$orderby=PaidOn desc&$skip=0&$top=12&$count=true
注意:
groupby中必须包含所有需要返回的父实体属性,否则查询结果仅会包含分组字段和聚合结果。
内容的提问来源于stack exchange,提问作者iraaa
相关产品推荐
相关产品推荐

