如何跨天蓝色存储表中的多个分区键进行查询?

发布于 2025-01-10 14:09:02 字数 1474 浏览 0 评论 0原文

我有以下用例:

  • 用户请求创建一个小部件。使用我的存储表中“请求”分区中的详细信息创建一条新记录。
  • 当请求得到满足时 - 原始请求将从“请求”分区中删除,并在“已配置”分区中重新创建。

当涉及到查询小部件时 - 我需要搜索请求和配置的分区。 从阅读文档来看,我似乎可以创建过滤器?但这似乎是很大的开销,因为我知道我只会返回 1 条记录(希望如此,除非我有错误)。 但看来我必须添加很多逻辑来处理分页。

到目前为止,这就是我要从:

 entity = tableClient.GetEntity<TableEntity>(
        "requested",
         requestId); 

到类似这样的内容:

            //entity = tableClient.GetEntity<TableEntity>(
            //                    "requested",
            //                    requestId); 

            List<string> filters = new List<string>();
            filters.Add($"PartitionKey eq '{"requested"}'");
            filters.Add($"PartitionKey eq '{"provisioned"}'");
            filters.Add($"RowKey eq '{requestId}'");
            string filter = String.Join(" and ", filters);
            //should only ever return one ... but ...
            var entities =  tableClient.QueryAsync<TableEntity>(filter);

            await foreach (Page<TableEntity> page in entities.AsPages())
            {
                Console.WriteLine("This is a new page!");
                foreach (TableEntity qEntity in page.Values)
                {
                    Console.WriteLine($"i found this request:  {qEntity.GetString("requestId")} with status: {"status"}");
                }
            }

此代码目前不起作用 - 将需要对其进行调试。但我想我应该检查一下是否有更简单的方法来做到这一点。

谢谢。

I have the following use case:

  • user requests creation of a widget. A new record is created with the details in a "request" partition in my storage table.
  • when the request is fulfilled - the original request is deleted from the "request" partition and created anew in the "provisioned" partition.

When it comes to querying for a widget - I need to search both the request and provisioned partitions.
From reading the docs, it seems that I can create filters? But it seems to be a lot of overhead because I know i will only ever have 1 record returned (hopefully, unless I have a bug).
But it seems I have to add a lot of logic to handle pagination.

So far this is what i'm moving from:

 entity = tableClient.GetEntity<TableEntity>(
        "requested",
         requestId); 

To something like this:

            //entity = tableClient.GetEntity<TableEntity>(
            //                    "requested",
            //                    requestId); 

            List<string> filters = new List<string>();
            filters.Add(
quot;PartitionKey eq '{"requested"}'");
            filters.Add(
quot;PartitionKey eq '{"provisioned"}'");
            filters.Add(
quot;RowKey eq '{requestId}'");
            string filter = String.Join(" and ", filters);
            //should only ever return one ... but ...
            var entities =  tableClient.QueryAsync<TableEntity>(filter);

            await foreach (Page<TableEntity> page in entities.AsPages())
            {
                Console.WriteLine("This is a new page!");
                foreach (TableEntity qEntity in page.Values)
                {
                    Console.WriteLine(
quot;i found this request:  {qEntity.GetString("requestId")} with status: {"status"}");
                }
            }

This code presently doesn't work - will need to debug it. but I thought i'd check to see if there's an easier way to do this.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

楠木可依 2025-01-17 14:09:02

我建议首先编写一个 TryGetEntityAsync 扩展方法:

public static async Task<Response<T>?> TryGetEntityAsync<T>(this TableClient tableClient, string partitionKey, string rowKey, IEnumerable<string>? select = default, CancellationToken cancellationToken = default) where T : class, ITableEntity, new()
{
  try
  {
    return await tableClient.GetEntityAsync<T>(partitionKey, rowKey, select, cancellationToken);
  }
  catch (RequestFailedException ex) when (ex.Status == 404)
  {
    return null;
  }
}

然后,您可以一次执行一个点查询:

var entity =
    (await tableClient.TryGetEntityAsync<TableEntity>("requested", requestId)) ??
    (await tableClient.TryGetEntityAsync<TableEntity>("provisioned", requestId));

或同时执行:

var requestedEntityTask = tableClient.TryGetEntityAsync<TableEntity>("requested", requestId);
var provisionedEntityTask = tableClient.TryGetEntityAsync<TableEntity>("provisioned", requestId);
var entities = await Task.WhenAll(requestedEntityTask, provisionedEntityTask);
var entity = entities[0] ?? entities[1];

I would recommend first writing a TryGetEntityAsync extension method:

public static async Task<Response<T>?> TryGetEntityAsync<T>(this TableClient tableClient, string partitionKey, string rowKey, IEnumerable<string>? select = default, CancellationToken cancellationToken = default) where T : class, ITableEntity, new()
{
  try
  {
    return await tableClient.GetEntityAsync<T>(partitionKey, rowKey, select, cancellationToken);
  }
  catch (RequestFailedException ex) when (ex.Status == 404)
  {
    return null;
  }
}

Then, you can do two point queries one at a time:

var entity =
    (await tableClient.TryGetEntityAsync<TableEntity>("requested", requestId)) ??
    (await tableClient.TryGetEntityAsync<TableEntity>("provisioned", requestId));

or concurrently:

var requestedEntityTask = tableClient.TryGetEntityAsync<TableEntity>("requested", requestId);
var provisionedEntityTask = tableClient.TryGetEntityAsync<TableEntity>("provisioned", requestId);
var entities = await Task.WhenAll(requestedEntityTask, provisionedEntityTask);
var entity = entities[0] ?? entities[1];
弱骨蛰伏 2025-01-17 14:09:02

考虑到一个实体仅存在于一个分区中,您可以将代码更改为:

List<string> filters = new List<string>();
filters.Add($"(PartitionKey eq 'requested' and RowKey eq '{requestId}')");
filters.Add($"(PartitionKey eq 'provisioned' and RowKey eq '{requestId}')");
string filter = String.Join(" or ", filters);
//should only ever return one ... but ...
var entities =  tableClient.QueryAsync<TableEntity>(filter);

await foreach (Page<TableEntity> page in entities.AsPages())
{
    Console.WriteLine("This is a new page!");
    foreach (TableEntity qEntity in page.Values)
    {
        Console.WriteLine($"i found this request:  {qEntity.GetString("requestId")} with status: {"status"}");
    }
}

Considering an entity will be present in just one partition only, you could change your code to something like:

List<string> filters = new List<string>();
filters.Add(
quot;(PartitionKey eq 'requested' and RowKey eq '{requestId}')");
filters.Add(
quot;(PartitionKey eq 'provisioned' and RowKey eq '{requestId}')");
string filter = String.Join(" or ", filters);
//should only ever return one ... but ...
var entities =  tableClient.QueryAsync<TableEntity>(filter);

await foreach (Page<TableEntity> page in entities.AsPages())
{
    Console.WriteLine("This is a new page!");
    foreach (TableEntity qEntity in page.Values)
    {
        Console.WriteLine(
quot;i found this request:  {qEntity.GetString("requestId")} with status: {"status"}");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文