0

那么我的要求是做客户端分页。即根据客户端给出的值($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);
}

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

4

3 回答 3

0

这是您的代码的更新版本,它使用 的通用版本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);
}
于 2013-10-07T14:01:09.057 回答
0

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

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

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

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

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

如果有超过 1,000 个预订,但数量不多,您可以在服务器端对它们进行分页,用尽集合,然后将所有预订交付回 OData 客户端,或者对它们进行排序并允许 IQueryable 对该集合进行查询。见注,底部。

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

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

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

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

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

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

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

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

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

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

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

这意味着我上面建议对数据子集/数据组提供分页,要求将整个子集带入服务层并对其应用排序顺序,然后再应用顶部和跳过,尽管可以说客户应该明白,没有订单的顶部/跳过是没有意义的,他们有责任发送正确的选项。

于 2015-01-29T22:49:15.717 回答
0

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

几个区别:

我有一个暴露我的实体的服务层。在我的服务中,我返回 IQueryable 并应用 O Data 过滤器。

    [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());
    }
于 2013-10-07T13:53:45.897 回答