【问题标题】:Can't apply $select when using ODataQueryOptions使用 ODataQueryOptions 时无法应用 $select
【发布时间】:2019-09-02 07:21:00
【问题描述】:

我正在尝试通过 EF Core 和 OData(7.1.0) 实现对 Sql Server 的查询。

动作方法如下:

[HttpGet]
public IEnumerable<UserInfoDto> Get(ODataQueryOptions ops)
{
     return this.service.GetUserInfos(ops);
}

服务代码:

public List<UserInfoDto> GetUserInfos(ODataQueryOptions ops)
{
    using (var context = new EFContext())
    {
        var query = context.Users.Join(context.Customers, x => x.CustomerId, y => y.Id, (x, y) => new UserInfoDto
        {
            Id = x.Id,
            Name = x.Name,
            Age = x.Age,
            CustomerId = x.CustomerId,
            CustomerTitle = y.Title,
            CustomerDescription = y.Description
        });

        var result = ops.ApplyTo(query).Cast<UserInfoDto>().ToList();
        return result;
    }
}

启动Configute方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
     app.UseMvc(b => 
     {
         b.Count().Filter().OrderBy().Select().MaxTop(null);
         b.EnableDependencyInjection();
     });
}

但是,当我在查询中使用 $select(例如 https://localhost:5001/api/userinfos?$select=id)时,我收到的不是预测结果,而是一个错误:

InvalidOperationException:类型之间没有定义强制运算符 'Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[小田 taApp.UserInfoDto]' 和 'OdataApp.UserInfoDto'。



我错过了什么?任何帮助表示赞赏。

【问题讨论】:

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


    【解决方案1】:

    当您对 OData 使用 $select 查询选项时,您需要 dynamic 的 IQueryable。

    例如,想象以下类:

    public class Person {
        public int Id { get; set }
        public string Name { get; set; }
    }
    
    

    因此,如果您有一个没有$select 的查询,IQueryable 将生成一个 Person 集合,其中包含每个项目中的所有属性(id 和 name)。

    但是,如果您使用 $select=id 查询,每个项目将只有 ID 属性,您不能将动态类型转换为 Person 类型。

    换句话说,你不能使用$select并返回一个List&lt;UserInfoDto&gt;,你需要在没有Cast方法的情况下返回一个List&lt;dynamic&gt;,就像这样:

        var result = ops.ApplyTo(query) as IQueryable<dynamic>;
        return result.ToList();
    

    编辑:

    方法的完整实现将是:

    // changing the return type
    public List<dynamic> GetUserInfos(ODataQueryOptions<UserInfoDto> ops)
    {
        using (var context = new EFContext())
        {
            var query = context.Users.Include(Customers, x => x.CustomerId, y => y.Id, (x, y) => new UserInfoDto
            {
                Id = x.Id,
                Name = x.Name,
                Age = x.Age,
                CustomerId = x.CustomerId,
                CustomerTitle = y.Title,
                CustomerDescription = y.Description
            });
            // casting the applyto result
            var result = ops.ApplyTo(query) as IQueryable<dynamic>;
            return result.ToList();
        }
    }
    

    【讨论】:

    • 谢谢,我会试一试,让你知道它是否适合我 c:
    • 是的,经过你的解释,我觉得事情变得很合乎逻辑了!由于 OData $select 不涵盖我需要的几个复杂查询,我想我将继续使用静态 DTO 并完全禁止 $select 操作。无论如何,非常感谢您的帮助!
    • 'System.Linq.EnumerableQuery1[System.Object]' cannot be converted to type 'System.Linq.IQueryable1[DtoExample] 类型的对象
    • @Jackie 你解决了吗
    • @rodrigo Jackie 发布的问题/错误是在移除铸件后,$select 仍然不起作用
    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2015-08-18
    • 2015-01-28
    相关资源
    最近更新 更多