C# 如何使用OData在azure表存储API上进行分页?

C# 如何使用OData在azure表存储API上进行分页?,c#,azure,asp.net-web-api,pagination,odata,C#,Azure,Asp.net Web Api,Pagination,Odata,我的要求是做客户端分页。i、 e根据客户端给定的值($top,$skip)返回一组记录。但基于我下面的代码,我只能使用过滤关键字和top或skip [HttpGet] public PageResult<PersistedUser> GetAllUsers(ODataQueryOptions options) { TableServiceContext serviceContext = tableClient.GetDataServiceContext();

我的要求是做客户端分页。i、 e根据客户端给定的值($top,$skip)返回一组记录。但基于我下面的代码,我只能使用过滤关键字和top或skip

[HttpGet]        
public PageResult<PersistedUser> GetAllUsers(ODataQueryOptions options)
{
    TableServiceContext serviceContext = tableClient.GetDataServiceContext();
    serviceContext.IgnoreResourceNotFoundException = true;

    CloudTableQuery<PersistedUser> users = serviceContext
        .CreateQuery<PersistedUser>(TableNames.User)
        .AsTableServiceQuery();    

    IQueryable<PersistedUser> results = options
        .ApplyTo(users.AsQueryable()) as IQueryable<PersistedUser>;

    // manipulate results. Add some calculated variables to the collection etc

    return new PageResult<PersistedUser>(results, null, 0);
}
[HttpGet]
公共页面结果GetAllUsers(ODataQueryOptions选项)
{
TableServiceContext serviceContext=tableClient.GetDataServiceContext();
serviceContext.IgnoreResourceNotFoundException=true;
CloudTableQuery用户=serviceContext
.CreateQuery(TableNames.User)
.AsTableServiceQuery();
IQueryable结果=选项
.ApplyTo(users.AsQueryable())作为IQueryable;
//操作结果。向集合中添加一些计算变量等
返回新的PageResult(results,null,0);
}

我不确定这是否也是正确的方法。但我的基本要求是我有一个巨大的数据库,但我只需要在一个有效的时间内一次返回一组小的实体。如果有人能提供一些代码片段,我将不胜感激。

我也在用同样的方法,而且效果很好

几乎没有区别:

我有一个公开我的实体的服务层。在我的服务中,我返回IQueryable并应用O数据过滤器

    [AuthKey]
    [GET("api/brands/")]
    public PageResult<BrandViewModel> GetBrands(ODataQueryOptions<Brand> options)
    {
        var brands = (IQueryable<Brand>)options.ApplyTo(_brandServices.FindBrands());

        return new PageResult<BrandViewModel>(BrandViewModel.ToViewModel(brands), Request.GetNextPageLink(), Request.GetInlineCount());
    }
[AuthKey]
[获取(“api/品牌/”)]
公共页面结果GetBrands(ODataQueryOptions选项)
{
var brands=(IQueryable)options.ApplyTo(_brandServices.FindBrands());
返回新的PageResult(BrandViewModel.ToViewModel(brands)、Request.GetNextPageLink()、Request.GetInlineCount());
}

这是您的代码的更新版本,它使用了
ODataQueryOptions
的通用版本,并将
$top
$skip
选项应用于分页

[HttpGet]        
public PageResult<PersistedUser> GetAllUsers(
    ODataQueryOptions<PersistedUser> options)
{
    TableServiceContext serviceContext = tableClient.GetDataServiceContext();
    serviceContext.IgnoreResourceNotFoundException = true;

    CloudTableQuery<PersistedUser> users = serviceContext
        .CreateQuery<PersistedUser>(TableNames.User)
        .AsTableServiceQuery();    

    IQueryable<PersistedUser> results = options.ApplyTo(users);

    int skip = options.Skip == null ? 0 : options.Skip.Value;
    int take = options.Top == null ? 25 : options.Top.Value;

    return new PageResult<PersistedUser>(
        results.Skip(skip).Take(take).ToList(), 
        Request.GetNextPageLink(),
        null);
}
[HttpGet]
公共页面结果GetAllUsers(
ODataQueryOptions(选项)
{
TableServiceContext serviceContext=tableClient.GetDataServiceContext();
serviceContext.IgnoreResourceNotFoundException=true;
CloudTableQuery用户=serviceContext
.CreateQuery(TableNames.User)
.AsTableServiceQuery();
IQueryable结果=options.ApplyTo(用户);
int skip=options.skip==null?0:options.skip.Value;
int take=options.Top==null?25:options.Top.Value;
返回新页面结果(
results.Skip(Skip).Take(Take).ToList(),
Request.GetNextPageLink(),
无效);
}

规划OData模型时,请将其与基础存储模型分开。在某些域中,可以先公开组,然后使用导航属性访问组的成员

例如,假设您有一个预订系统。您可以按日期时间将预订存储在一张长长的表格中

但是,您可以将OData模型分组为年和周的集合,从而潜在地公开它

在控制器中,可以根据提供的时态参数组合表存储范围查询

如果有超过1000个预订,但数量不多,您可以在服务器端翻页浏览这些预订,耗尽集合,然后将所有预订返回到OData客户端,或者对它们进行排序,并允许IQueryable在该集合上进行访问。见注,底部

这将为OData消费者提供一种自然的机制来过滤数据,同时保持结果集的大小较低。如果每周有许多预订,则可以按星期和小时进一步细分

这完全是理论上的,但我认为ODataV4及其包含特性将允许路由此类URL并描述关系,以便为OData消费者(如Excel)生成正确的元数据

请注意,在上面的示例代码中,它们创建了一个任意的路由/URL来计算包含的项目,因此它看起来很灵活

如果不允许嵌套包容,则可选地,在ODATA EDM中考虑一个具有年和周属性的BoungRangGrand实体,以允许:

我考虑过的另一个想法是在insert上计算页码。也就是说,在TS实体本身上有一个页码,并使用算法为其分配一个页码。这基本上与生成一个好的分区键相同,但是有很多页/分区

一个希望容纳2亿行的表可能有1百万页(生成一个大的psuedo随机数并将其修改1百万),每个页面包含200项。起初,大多数页面都是空的,所以您需要编写一个页面映射器算法,该算法会随着行数的增加而改变。“页面”1映射到页面范围0000001-0000100等

正如您所看到的,这变得越来越复杂,但它本质上是Azure用来自动平衡分区之间的数据并将这些分区分布在其节点上的同一个系统

最终,这将再次需要一种在URL中指定“页面”编号的方法。最后,根据所用算法的分布情况,每个页面将包含不同数量的项目

注意-我认为TS不支持top和skip或skip的原因是无法保证返回行的顺序,并且TS中没有排序机制(这将是一个很大的负担)。因此,从顶部和跳过的页面每次都会包含一个“随机”包


这意味着我在上面提出的对数据子集/组进行分页的建议,要求在应用top和skip之前,将整个子集放入服务层并应用排序顺序,尽管可以说,客户应该明白,没有订单的top/skip是没有意义的,他们有责任发送正确的选项。

您可能需要记住的一点是,表存储本身并不支持所有OData功能(例如,$skip不受支持)因此,您需要在您的服务层中自己管理它。是的,我知道表存储不支持所有这些操作。这就是为什么我想知道怎么做。如果我