10

我想用一个简单的 TableQuery 从我的 Azure 表中获取前n行。但是使用下面的代码,无论我对 Take 的限制如何,都会获取所有行。

我究竟做错了什么?

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 条记录,您仍然可以按时停止迭代。

在您的示例中,您应该修改 while 循环以在达到 TakeCount(您通过调用 Take 设置)时停止:

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 存储客户端库 2.0 在 Take 实现中有一个错误。它已在 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-tables-deep-dive

于 2013-04-04T07:07:20.240 回答