10

簡単な TableQuery を使用して、Azure テーブルから上位n行を取得したいと考えています。しかし、以下のコードでは、テイクの制限に関係なく、すべての行がフェッチされます。

私は何を間違っていますか?

int entryLimit = 5;

var table = GetFromHelperFunc();

TableQuery<MyEntity> query = new TableQuery<MyEntity>()
    .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "MyPK"))
    .Take(entryLimit);

List<FeedEntry> entryList = new List<FeedEntry>();
TableQuerySegment<FeedEntry> currentSegment = null;

while (currentSegment == null || currentSegment.ContinuationToken != null)
{
    currentSegment = table.ExecuteQuerySegmented(query, this.EntryResolver, currentSegment != null ? currentSegment.ContinuationToken : null);
    entryList.AddRange(currentSegment.Results);
}


Trace.WriteLine(entryList.Count) // <-- Why does this exceed my limit?
4

2 に答える 2

17

ストレージ SDK の Take メソッドは、LINQ のようには機能しません。次のようなことをすると想像してください。

TableQuery<TableEntity> query = new TableQuery<TableEntity>()
                .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp"))
                .Take(5);
var result = table.ExecuteQuery(query);

反復を開始すると、result最初は 5 つのアイテムしか得られません。しかし、その下で、 を反復し続けるresultと、SDK はテーブルのクエリを続けます (そして、5 つの項目の次の「ページ」に進みます)。

テーブルに 5000 個のアイテムがある場合、このコードは 5000 個のアイテムすべてを出力します (そして、SDK の下で 1000 個のリクエストを実行し、リクエストごとに 5 個のアイテムをフェッチします)。

TableQuery<TableEntity> query = new TableQuery<TableEntity>()
                .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp"))
                .Take(5);
var result = table.ExecuteQuery(query);
foreach (var item in result)
{
    Trace.WriteLine(item.RowKey);
}

次のコードは、1 回のリクエストで正確に 5 個のアイテムを取得し、そこで停止します。

TableQuery<TableEntity> query = new TableQuery<TableEntity>()
                .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "temp"))
                .Take(5);
var result = table.ExecuteQuery(query);
int index = 0;
foreach (var item in result)
{
    Console.WriteLine(item.RowKey);
    index++;
    if (index == 5)
        break;
}

実際には、Take()メソッドはページ サイズまたは「テイク カウント」( TableQueryの TakeCountプロパティ) を設定します。ただし、必要なレコードが 5 つだけの場合は、時間どおりに反復を停止するかどうかはあなた次第です。

あなたの例では、TakeCount (Take を呼び出して設定したもの) に達したときに停止するように while ループを変更する必要があります。

while (entryList.Count < query.TakeCount && (currentSegment == null || currentSegment.ContinuationToken != null))
{
    currentSegment = table.ExecuteQuerySegmented(query, currentSegment != null ? currentSegment.ContinuationToken : null);
    entryList.AddRange(currentSegment.Results);
}
于 2012-11-19T12:19:39.057 に答える
10

AFAIK Storage Client Library 2.0 には、Take の実装にバグがありました。ver 2.0.4 で修正されました。http://blogs.msdn.com/b/windowsazurestorage/archive/2012/11/06/windows-azure-storage-client-library-2-0-tables-deep-dive.aspx
で最後のコメントを読む

[編集] 元の MSDN 投稿は利用できなくなりました。まだ WebArchive に存在: http://web.archive.org/web/20200722170914/https://docs.microsoft.com/en-us/archive/blogs/windowsazurestorage/windows-azure-storage-client-library-2 -0 テーブルの詳細

于 2013-04-04T07:07:20.240 に答える