使用存储过程自定义分页与OData源C#无实体框架

Jim*_*nes 9 c# pagination odata asp.net-web-api2 powerbi

我想知道是否有人可以帮助我,一段时间以来我一直试图弄清楚如何在OData feed(v4)Web API 2中实现自定义分页以提供功率bi feed并且没有成功.

数据首先来自数据库,数据库并且是使用连接的5个表的组合,这使得它不适合与实体框架一起使用,除了实体框架(一个控制器中的45k个记录)真的很慢.

我已经尝试了许多不同的方法,设置记录的总量来欺骗框架并将分页结果填充到列表的空成员,到下面的更基本的例子.但是,我仍然无法获取客户端(Power BI)正确获取分页结果,而无需从控制器返回大量的记录.请参阅简化的查询和代码,非常欢迎任何帮助,因为似乎没有明确的示例说明如何在不使用Entity Framework的情况下执行此操作.

下面的代码可以工作,但是我继续有相同问题的变体,框架在它返回之后在列表上进行分页,尽管我之前做了什么

T-SQL存储过程:

CREATE PROCEDURE [dbo].[GetOrders] @CompanyID int,
                                   @Skip INT,
                                   @Take INT
AS

BEGIN 

SET NOCOUNT ON;

SELECT *
FROM Orders 
WHERE CompanyID = @CompanyID
ORDER BY t.OrderID
OFFSET @Skip ROWS FETCH NEXT @Take  ROWS ONLY

END
Run Code Online (Sandbox Code Playgroud)

指向调用上述查询的repo的控制器

[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;
}
Run Code Online (Sandbox Code Playgroud)

在此之后完成框架的分页return response;.

Jim*_*nes 0

我最终找到的解决方案是通过扩展 EnableQueryAttribute 来中断框架(假设您关闭过滤等并设置最大页面大小)。在分页查询中,您需要转到页面上方的一个来触发内部机制,此解决方案只是一种解决方法。关键是在“ApplyTo”之前将 Take 设置为 0。

IEnumerable<Order> results = await _OrderRepo.GetAll(CompanyID, Skip, Take + 1);
Run Code Online (Sandbox Code Playgroud)

分页属性

public sealed class PagingAttribute : EnableQueryAttribute
{
    public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
    {
        var result = default(IQueryable);
        var originalRequest = queryOptions.Request;

        var skip = queryOptions.Skip == null ? 0 : queryOptions.Skip.Value;
        var take = queryOptions.Top == null ? PageSize : queryOptions.Top.Value;

        queryOptions = ODataQueryOptionsUtilities.Transform(queryOptions, new ODataQueryOptionsUtilitiesTransformSettings { Skip = (map, option) => default(int?) });

        if (queryOptions.Request.ODataProperties().TotalCount != null)
            originalRequest.ODataProperties().TotalCount = originalRequest.GetInlineCount();

        result = queryOptions.ApplyTo(queryable);

        if (skip + take <= originalRequest.ODataProperties().TotalCount)
            originalRequest.ODataProperties().NextLink = NextPageLink.GetNextNewPageLink(originalRequest, (skip + take));

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在控制器中设置了以下内容

        originalRequest.ODataProperties().TotalCount = Query.Item1; // Total size of all records to be returned
        originalRequest.SetInlineCount(Query.Item1);
Run Code Online (Sandbox Code Playgroud)