在 WebAPI 中使用 OData 时如何将 SelectExpandQueryOption 转换为 IQueryable<T>?

Posted

技术标签:

【中文标题】在 WebAPI 中使用 OData 时如何将 SelectExpandQueryOption 转换为 IQueryable<T>?【英文标题】:How to cast SelectExpandQueryOption to IQueryable<T> when using OData in WebAPI? 【发布时间】:2021-12-01 06:08:40 【问题描述】:

我有一个在 ASP.NET Core/5 框架之上用 C# 编写的 WebAPI。

我为我的 API 启用了odata。我正在尝试手动应用 odata 过滤器、order by 子句、选择列和扩展。

这是我尝试使用 ODataQueryOptions 手动构建查询的方式

protected IQueryable<TModel> BuildQuery(ODataQueryOptions<TModel> queryOptions, ODataQuerySettings settings)

    IQueryable<TModel> query = DbSet;

    if (queryOptions.SelectExpand != null)
    
        var queryable = queryOptions.SelectExpand.ApplyTo(query, settings);

        query = queryable.Cast<TModel>(); // this causes an error
    

    if (queryOptions.Filter != null)
    
        query = queryOptions.Filter.ApplyTo(query, settings) as IQueryable<TModel>;  // this works!
    

    if (queryOptions.OrderBy != null)
    
        query = queryOptions.OrderBy.ApplyTo(query); // this works!
    

    return query;

在我尝试扩展导航属性之前,上面的一切都很好。当我这样做时,我收到以下错误

System.InvalidOperationException: 'No coercion operator is defined between types 'Microsoft.AspNetCore.OData.Query.Wrapper.SelectAllAndExpand`1[MyModel]' and 'MyModel'.'

在定义IEdmModel 以构建导航关系时,是否需要进行某种映射?

如何正确地将IQueryable&lt;Microsoft.AspNetCore.OData.Query.Wrapper.SelectAllAndExpand&lt;TEntity&gt;&gt; 转换/转换为IQueryable&lt;TEntity&gt;

这是SelectAllAndExpand背后的代码

【问题讨论】:

可能是 ***.com/questions/55636167/… 的副本,您无法将 selectexpand 查询转换为已定义的模型,您需要将其转换为动态,想象当 query 是 IEnumerable 时的 LINQ 表达式,例如query.Select(t =&gt; new t.Id, t.Name ) 这个查询不能被强制转换为 IEnumerable,因为它生成一个匿名动态类型,selectexpand 也是如此,所以你需要改变你的方法来考虑一个 IQueryable 返回。 【参考方案1】:

你不能直接投射

var queryable = queryOptions.SelectExpand.ApplyTo(query, settings);

IQueryable&lt;TModel&gt;,因为它是不同类型的对象。

如果没有 Projection (Select) 或 Expand - 您将得到一个常规对象,但在 Projection 和 Expand 之后 - 这是完全不同的事情。 根据您的任务,您应该处理SelectAllAndExpand&lt;TModel&gt; 或删除SelectExpand.ApplyTo(..)

【讨论】:

以上是关于在 WebAPI 中使用 OData 时如何将 SelectExpandQueryOption 转换为 IQueryable<T>?的主要内容,如果未能解决你的问题,请参考以下文章

您如何将乐观并发与 WebAPI OData 控制器一起使用

使用 EF 和 WebAPI,如何返回 ViewModel 并支持 IQueryable/OData? [复制]

WebAPI OData v4 查询不是异步的?

在 ASP.NET Core WebAPI 中获取 OData 计数

OData WebAPI 2 复杂授权

将 ODATA $expand 查询选项与 WebAPI 和 ViewModel 一起使用