【问题标题】:Combining LINQ with OData AddQueryOption将 LINQ 与 OData AddQueryOption 相结合
【发布时间】:2015-07-20 09:49:04
【问题描述】:

OData (listed here) 的限制使我无法从我的 OData 源向数据集添加动态 where 子句。我找到了一个previous post,它回答了我对动态过滤器的查询,即使用带有自定义构建查询字符串的 AddQueryOption 方法。但是,似乎没有办法将此查询字符串与标准 LINQ 查询结合起来。

使用上述方法产生一个有效的查询:

https://api-dev.company.com/odata/Assets?$filter=(Levels/any(l:l/LevelId eq 18)) or (Levels/any(l:l/LevelId eq 19))

之所以必须动态生成,是因为存在数量可变的级别过滤器,这些过滤器在运行时之前无法确定,并且简单地使用多个 Where 子句会生成“and”过滤器而不是“or”过滤器,如下所示:

https://api-dev.company.com/odata/Assets?$filter=(Levels/any(l:l/LevelId eq 18)) and (Levels/any(l:l/LevelId eq 19))

在此方法产生以下输出后,我当前尝试使用 LINQ:

https://api-dev.company.com/odata/Assets?$filter=DisplayOnline and Status eq Tools.Services.Models.EPublishStatus'Active', and (Levels/any(l:l/LevelId eq 18)) or (Levels/any(l:l/LevelId eq 19))

请注意,第二个查询的唯一问题是 Levels 过滤器和其余过滤器之间的逗号。

额外的Where子句如下:

// Filter by assets that can be displayed online
assets = assets.Where(a => a.DisplayOnline);

// Filter by assets that are active
assets = assets.Where(a => a.Status == EPublishStatus.Active);

我想知道是否有手动编辑字符串的方法,或者是否有适当的方法来组合两种查询字符串生成方法。感谢您的宝贵时间。

【问题讨论】:

    标签: c# .net linq odata


    【解决方案1】:

    经过反复试验,我发现使用answered here 解决方案有助于解决这个问题。我的解决方案是在 LINQ Where 子句之后构建动态过滤器查询,然后使用两者的组合结果构建一个全新的查询:

    // Filter by assets that can be displayed online
    assets = assets.Where(a => a.DisplayOnline);
    
    // Filter by assets that are active
    assets = assets.Where(a => a.Status == EPublishStatus.Active);
    
    // Addtional filters..
    assets = assets.Where(a => x == y);
    
    // Get the string for the dynamic filter
    string dynamicQuery = GetDynamicQuery(assets);
    
    // Get base OData Asset call (https://api-dev.company.com/odata/Assets)
    IQueryable<Asset> serviceCall = _container.Assets;
    
    // Apply the new dynamic filter
    serviceCall = serviceCall.AddQueryOption("$filter", dynamicQuery);
    
    // Resultant OData query (Success!)
    https://api-dev.company.com/odata/Assets?$filter=DisplayOnline and Status eq Models.Status'Active' and (Levels/any(l:l/LevelId eq 18)) or (Levels/any(l:l/LevelId eq 19))
    

    这里的技巧是确保查询中只有一个“$filter”选项,否则会抛出异常。

    【讨论】:

      【解决方案2】:

      如果在调用 GetDynamicQuery(assets); 之前 where 子句中已经存在 DateTime 过滤器,则会出现错误 错误类似于使用新请求 URL message=The time zone information is missing on the DateTimeOffset value '2016-09-20T23:54:23.4531408'. A DateTimeOffset value must contain the time zone information. 调用 odata Web api 时 我已经发布了这个link

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-26
        • 1970-01-01
        • 2016-07-16
        • 2015-07-07
        • 1970-01-01
        • 2011-01-17
        • 1970-01-01
        • 2019-12-02
        相关资源
        最近更新 更多