繁体   English   中英

向 OData(v4) Web API C# 添加自定义分页

[英]Adding custom paging to OData(v4) Web API C#

我想知道有人可以帮助我。 我正在尝试将自定义分页实现到 OData 提要 (oData v4) 中。 我正在从一个存储过程填充 IEnumerable,我在下面添加了一种分页方法(工作完美)

SELECT  *
FROM  ( 
    SELECT    ROW_NUMBER() OVER ( ORDER BY OrderID ) AS RowNum, *
    FROM      dbo.Order
    WHERE     CompanyID = @CompanyID
) AS RowConstrainedResult
WHERE   RowNum >= @Start AND RowNum <= @Finish
ORDER BY RowNum

然而,我遇到的问题是,除了分页不起作用之外,下面的代码工作得很好

[EnableQuery]
public async Task<PageResult<Order>> GetOrders(ODataQueryOptions<Order> queryOptions)
{
    int CompanyID = User.Identity.GetCompanyID().TryParseInt(0);

    ODataQuerySettings settings = new ODataQuerySettings()
    {
        PageSize = 100,
    };

    int OrderCount = _OrderRepo.GetOrderCount(CompanyID);
    int Skip = 0;
    if (queryOptions.Skip != null)
    {
        Skip =  queryOptions.Skip.Value;
    }

    IEnumerable<Order> results = await _OrderRepo.GetAll(CompanyID, Skip, 100);

    IQueryable result = queryOptions.ApplyTo(results.AsQueryable(), settings);

    Uri uri = Request.ODataProperties().NextLink;
    Request.ODataProperties().TotalCount =  OrderCount;

    PageResult<Order> response = new PageResult<Order>(
    result as IEnumerable<Order>,
    uri, Request.ODataProperties().TotalCount);

    return response;
}

基本上,我试图以 100 个批次的方式翻阅结果,仅在需要时从数据库中取出 100 个。

当我第一次调用该控制器时,我得到了预期的结果。

http://localhost:24600/Data/Orders

但是,当我查询此 nextLink(如下)时,尽管数据库中有超过 50,000 个结果并且 IEnumerable 结果已正确更新,但我没有收到错误但没有结果。

http://localhost:24600/Data/Orders?$skip=100

如果有人帮助我解决这个问题,我将非常感激,因为我是使用 odata 的新手。

更新

看起来,它正在计算第一批的大小并将其作为总大小,即使我正在设置总大小。 它似乎无法超过初始大小。

您可以只返回完整的集合(作为IQueryable )并让 OData 处理分页:

[EnableQuery(PageSize = 100)]
public IQueryable<Order> Get()
{
    return _OrderRepo.GetAll(CompanyID); //Assuming this returns an IQueryable
}

OData 知道如何处理IQueryable并将使用.Top().Skip()来获取条目,这将由您的可查询提供程序转换为 SQL。 (大概是EF?)

我认为 EnableQuery 属性是问题所在。 似乎这告诉框架您希望它处理事情。 我下面的示例,sans 属性,是在 asp.net 核心上使用 odata(我认为唯一真正的区别是使用 ODataFeature 而不是 ODataProperties)...

public class ThingController : ODataController
{
    [HttpGet]
    public PageResult<Thing> GetThings(ODataQueryOptions<Thing> queryOptions)
    {
        var thingsToSkip = queryOptions?.Skip?.Value ?? 0;
        var pageSize = 10;

        var totalThings = GetThingCount();

        var pageOfThings = GetThings(thingsToSkip, pageSize);

        var showNextLink = thingsToSkip + pageOfItems.Count < totalThings;

        return new PageResult<Things>(pageOfThings,
            showNextLink ? Request.GetNextPageLink(pageSize) : null,
            totalThings);
    }

    private int GetThingCount()
    {
        return 21;
    }

    private List<Things> GetThings(int skip, int take)
    {
        return Enumerable.Range(0, TotalThingCount())
            .Select(r => new Thing { Id = r.ToString() })
            .Skip(skip)
            .Take(take)
            .ToList();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM