繁体   English   中英

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

[英]How to use OData to do pagination on azure table storage APIs?

好吧,我的要求是进行客户端分页。 即根据客户端给定的值($ top,$ skip)返回一组记录。 但是根据我下面的代码,只能使用filter关键字,并且可以使用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);
}

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

我正在使用相同的方式,并且工作正常。

差异不大:

我有一个服务层来展示我的实体。 在我的服务中,我返回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());
    }

这是代码的更新版本,该代码使用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);
}

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

例如,假设您有一个预订系统。 您可以按日期时间将预订存储在很长的桌子上。

但是您可以通过分组为年和周的集合来公开OData模型。

http://service.net/odata/year(2013)/week(22)/bookings

在您的控制器中,您将根据提供的时间参数组成一个表存储范围查询。

如果有超过1,000个预订,但数量不多,则可以在服务器端通过它们进行分页,用尽所有设置,然后将所有预订传递回OData客户端,或者对它们进行排序并允许IQueryable使用该设置。 请参阅底部的注释。

这将为OData使用者提供一种自然的过滤数据机制,同时保持结果集大小较小。 每周有很多预订的地方,可以按星期几和小时数将其进一步细分。

这完全是理论上的,但是我认为OData v4及其包含功能将允许对此类URL进行路由并描述其关系,以便为OData使用者(如Excel)生成正确的元数据。

http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-containment-in-web-api-22

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

如果不允许嵌套包含,则可以考虑使用具有Year和Week属性的OData EDM中的BookingRange实体,以允许:

http://service.net/odata/bookingrange(2013,22)/bookings

我考虑过的另一个想法是在插入时计算页码。 也就是说,在TS实体本身上具有PageNumber并使用算法为其分配页码。 这本质上与生成良好的分区键相同,但具有许多页面/分区。

预期容纳200m行的表可能具有100万个页面(生成一个大的伪随机数并将其修改为1m),每个页面包含200个项目。 首先,大多数页面将是空的,因此您需要编写一个页面映射器算法,该算法会随着行数的增加而改变。 “页面” 1映射到页面范围0000001-0000100,依此类推。

如您所见,这变得越来越复杂,但其本质上与Azure使用同一系统来跨分区自动平衡数据并将这些分区分布到其节点的系统相同。

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

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

这意味着我上面的建议是提供对一个子集/一组数据的分页,要求将整个子集带入服务层,并在应用顶部和跳过之前对它们应用排序顺序,尽管可能会认为客户应该理解,没有订单就没有顶/跳过是没有意义的,他们有责任发送正确的选择。

暂无
暂无

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

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