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

コントローラーでは、提供された一時パラメーターから Table Storage 範囲クエリを作成します。

1,000 を超える予約があり、それ以上の数ではない場合は、それらをサーバー側でページングし、セットを使い果たし、すべての予約を OData クライアントに戻すか、並べ替えて、このセットに対して IQueryable を許可することができます。下部の注を参照してください。

これにより、OData コンシューマは、結果セットのサイズを小さく保ちながら、データをフィルタリングするための自然なメカニズムを利用できます。1 週間あたりの予約数が多い場合は、曜日と時間ごとにさらにサブグループ化できます。

これは完全に理論上の話ですが、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 の BookingRange エンティティで Year および Week プロパティを許可することを検討してください。

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

私が検討したもう 1 つのアイデアは、挿入時にページ番号を計算することです。つまり、TS エンティティ自体に PageNumber を設定し、アルゴリズムを使用してそれにページ番号を割り当てます。これは基本的に適切なパーティション キーを生成することと同じですが、多くのページ/パーティションがあります。

200m 行を保持すると予想されるテーブルには、1m ページ (大きな疑似乱数を生成し、それを 1m ずつ変更) があり、それぞれに 200 項目があります。最初はほとんどのページが空なので、行数が増えるにつれて変化するページ マッパー アルゴリズムを記述する必要があります。「ページ」1 は、ページ範囲 0000001 ~ 0000100 などにマップされます。

ご覧のとおり、これは複雑になってきていますが、基本的には、Azure がパーティション間でデータを自動調整し、それらのパーティションをノード間で分散するために使用するのと同じシステムです。

最終的には、これにも「ページ」番号を URL で指定する方法が必要になります。最後に、各ページには、使用されるアルゴリズムの分布に応じて、さまざまな数のアイテムが含まれます。

- TS が top and skip または skip をサポートしていない理由は、返される行の順序が保証されず、TS 内に順序付けメカニズムがないためだと思います (これは大きな負担になります)。したがって、上から順に並べられたページとスキップには、毎回「ランダムな」バッグが含まれます。

これは、データのサブセット/グループに対してページングを提供するという上記の提案では、トップとスキップを適用する前に、サブセット全体をサービス層に持ち込んで並べ替え順序をそれらに適用する必要があることを意味します。クライアントは、注文のないトップ/スキップは無意味であり、正しいオプションを送信する責任があることを理解する必要があります。

于 2015-01-29T22:49:15.717 に答える