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;.
我最终找到的解决方案是通过扩展 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)