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

时间:2016-11-02 22:48:01

标签: c# .net asp.net-web-api asp.net-web-api2 odata-v4

我想知道是否有人能够帮助我。我正在尝试实现自定义分页到OData提要(oData v4)。我从一个存储过程填充IEnumerable,我在下面添加了一个分页方法(Working Perfect)

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。

更新

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

2 个答案:

答案 0 :(得分:1)

您只需返回完整集(如IQueryable)并让OData处理分页:

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

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

答案 1 :(得分:0)

我认为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();
    }