将OData Filter转换为IQueryable表达式时遇属性查找错误求助
问题解决:OData筛选时出现"Could not find a property named 'Id' on type 'Edm.Int32'"错误
类层次结构
public class Company { public ICollection<CompanyType> CompanyTypes { get; set; } = new List<CompanyType>(); } public class CompanyType { public int Id { get; set; } public string Name { get; set; } = string.Empty; public static implicit operator int(CompanyType companyType) => companyType.Id; }
控制器方法
public async Task<ActionResult<CompaniesResponse>> GetCompanies(ODataQueryOptions<GetCompaniesRequestV2> request) { }
目标实现代码
Task<ActionResult<CompaniesResponse>> GetCompanies(ODataQueryOptions<GetCompaniesRequestV2> request) { var expression = // 从查询中提取表达式 var query = new Query(request, expression); var result = await _mediator.Send(query); }
错误场景
执行OData查询 $filter=CompanyTypes/any(s: s/Id eq 1)&$skip=0&$top=2 时,抛出错误:
Could not find a property named 'Id' on type 'Edm.Int32'
已尝试的无效代码
//ODataQueryOptions<GetCompaniesRequestV2> request ... IQueryable queryable = Enumerable.Empty<Company>().AsQueryable(); queryable = request.Filter.ApplyTo(queryable, new ODataQuerySettings());
问题原因
CompanyType类中定义了隐式转换为int类型的操作符,OData构建EDM模型时会自动将CompanyType识别为Edm.Int32类型,而非包含Id、Name属性的复杂/实体类型。这导致筛选条件中访问s/Id时,OData认为当前类型是int,不存在Id属性,进而抛出错误。
解决步骤
1. 显式配置OData EDM模型
在OData模型配置中,手动将CompanyType注册为复杂类型或实体类型,覆盖隐式转换带来的自动识别:
public IEdmModel GetEdmModel() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); // 注册Company实体 builder.EntitySet<Company>("Companies"); // 若无需主键,注册为复杂类型 builder.ComplexType<CompanyType>(); // 若需将CompanyType作为实体(含主键),则使用: // builder.EntityType<CompanyType>().HasKey(ct => ct.Id); return builder.GetEdmModel(); }
2. 匹配ODataQueryOptions泛型参数
控制器方法中使用的ODataQueryOptions<GetCompaniesRequestV2>,需确保GetCompaniesRequestV2的属性结构与Company完全一致;或业务允许的话,直接使用ODataQueryOptions<Company>,避免模型不匹配导致的解析错误。
3. 正确提取筛选表达式
若需将OData筛选转换为表达式树,针对Company类型处理:
// 假设request为ODataQueryOptions<Company> var filterExpression = request.Filter?.ApplyTo( Enumerable.Empty<Company>().AsQueryable(), new ODataQuerySettings() ).Expression as Expression<Func<Company, bool>>;
内容的提问来源于stack exchange,提问作者w.johnny
相关产品推荐
相关产品推荐

