带有 Odata-V4 和 Dapper 的 Web Api - 服务器端过滤

WebApi with Odata-V4 and Dapper - Serverside filtering

我们使用 ASP.Net Webapi 与 OData 和 Dapper 作为 ORM。对于 GET 请求,我们分别使用选项参数对象和它的过滤器参数来为 Dapper 查询构建 SQL 字符串。这适用于列 eq 值等。

但现在我想做一些服务器端分页。这意味着我使用两个过滤器($top 和 $skip)发出请求。例如。 "https://api.server.com/Orders?$skip=100&$top=50。Dapper 向数据库发出正确的请求,我得到一个包含 50 个条目的结果作为来自 dapper 的响应。

然后我将此结果放入 webapi 控制器的 return 语句中,webapi 似乎自行进行过滤。因此它执行从 50 的结果中跳过 100,这导致 0 个条目。

有没有人遇到同样的问题并找到了一种方法来阻止webapi过滤但将过滤委托给ORM?编写 ApiControllers 而不是 ODataControllers 是别无选择,因为我真的很喜欢使用 odata 语法进行过滤。

感谢您的回答!

假设您的 API 操作的 return 类型是 IQueryable,那么框架将对从数据库 return 编辑的任何数据应用查询过滤器,所以让我们包装查询结果进入 PageResult 和 return 它,它不会再次应用过滤器。示例代码如下-

public PageResult<Orders> GetOrdersPage(ODataQueryOptions<Orders> queryOptions)
{
    // Parse queryOptions to get Top and Skip
    var top = queryOptions.Top.RawValue;
    var skip = queryOptions.Skip.RawValue;

    //Call the dataaccess method and then get Querable result
    var queryResults = dataAccess.GetOrders(top,skip).AsQuerable<Orders>();

    //Return Page result 
    return new PageResult<Orders>(queryResults, new URI("Next page URI"), 1234); //1234 - is total count of records in table
}

我们通过下面的代码片段修复了它,这提供了放弃 [EnableQuery] 属性的解决方案:

public async Task<IHttpActionResult> Get(ODataQueryOptions<vwABC> options) 
    { 
        if(options != null && options.SelectExpand != null)
        {
            options.Request.ODataProperties().SelectExpandClause = options.SelectExpand.SelectExpandClause; 
        }
        if(options != null && options.Count != null && options.Count.Value == true)
        {
            options.Request.ODataProperties().TotalCount = await base.GetCount("vwABC", options);
        }
        return await base.Get(options, "vwABC"); 
    }