【问题标题】:Read more than 1000 rows from Azure Table Storage OData filter query?从 Azure 表存储 OData 筛选器查询中读取超过 1000 行?
【发布时间】:2020-10-17 14:56:28
【问题描述】:

我们如何从 Azure 表存储中读取超过 1000 行?这是我用于从表存储读取数据的代码,它只检索 1000 行:

readData()
{
    var s = @$"https://{storageAccountName}.table.core.windows.net/{tableName}()";          
    var baseurl = $"{s}<sas-token>&$filter=Name%20eq%20'XYZ'";
    var data = GetForOData(baseurl);
    var responseData = data.Data.Replace(".", "_");
    var odata = JsonConvert.DeserializeObject<ODataResponse>(responseData); 
}

GetForOData(string url) {return InvokeForOData<Object>("GET", url, null, null);}

private static HttpResponseData InvokeForOData<T>(string method, string url, Object id, T data)
{
    var Response = new HttpResponseData()
    {
         Code = HttpStatusCode.RequestTimeout, Data = string.Empty, Message = string.Empty
    };
            
    var PostParam = string.Empty;
    if (data != null) { PostParam = data.ToString(); }
    var postData = Encoding.UTF8.GetBytes(PostParam);
    var request = (HttpWebRequest)WebRequest.Create(new Uri(url + (id == null ? "" : '/' + id.ToString())));
     request.Method = method;
     // add headers
     if (postData.Length > 0)
     {
        using (Stream requestStream = request.GetRequestStream())
        { requestStream.Write(postData, 0, postData.Length); }
     }
     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
     {
        Response.Code = response.StatusCode;
        using (var stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
        { Response.Data = stream.ReadToEnd(); }
     }            
     return Response;
}

在哪里检查 x-ms-continuation-NextPartitionKey 和 x-ms-continuation-NextRowKey 并在下一个请求中使用它们?

更新:我能够找到 nextPartitionKey 和 nextRowKey 标头值。如何在下一个请求中传递这些值?

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    Response.Code = response.StatusCode;
                    var nextPartitionKey = response.Headers["x-ms-continuation-NextPartitionKey"];
                    var nextRowKey = response.Headers["x-ms-continuation-NextRowKey"];
                    using (StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
                    {
                        Response.Data = stream.ReadToEnd();
                    }
                }

【问题讨论】:

  • 嘿,有一个 Nuget 包可以简化表存储的使用,所以你可以忘记nuget.org/packages/Azure.Storage.Blobs 之间的 HTTP
  • @Pablo Recalde 谢谢 - 所以在安装 nuger 包后,我可以删除行 var data = HttpHelper.GetForOData(baseurl) 吗?
  • @Dennis1679 谢谢 - 您建议的链接使用 LINQ (CreateQuery),我正在使用 OData 过滤器查询。很想知道我的代码中要进行的更改。

标签: c# azure-table-storage


【解决方案1】:

对 Azure 表存储的一次调用将返回最多 1000 个实体。如果有更多实体与查询匹配,您将获得一个继续令牌,您将需要使用它来获取下一组实体。

因此,在您的情况下,为了读取 1000 多个实体,您必须发送请求、获取数据并检查响应中的延续令牌(x-ms-continuation-NextPartitionKeyx-ms-continuation-NextRowKey)并在接下来使用它们请求。

您可以在此处了解有关 Azure 表存储中分页的更多信息:https://docs.microsoft.com/en-us/rest/api/storageservices/query-timeout-and-pagination

更新

请看下面的代码(虽然未经测试):

private static HttpResponseData InvokeForOData<T>(string method, string url, Object id, T data)
{
  var Response = new HttpResponseData()
  {
        Code = HttpStatusCode.RequestTimeout, 
        Data = string.Empty, 
        Message = string.Empty,
        NextPartitionKey = string.Empty,
        NextRowKey = string.Empty
  };
            
  var PostParam = string.Empty;
  if (data != null) { PostParam = data.ToString(); }
  var postData = Encoding.UTF8.GetBytes(PostParam);
  var request = (HttpWebRequest)WebRequest.Create(new Uri(url + (id == null ? "" : '/' + id.ToString())));
    request.Method = method;
    // add headers
    if (postData.Length > 0)
    {
      using (Stream requestStream = request.GetRequestStream())
      { requestStream.Write(postData, 0, postData.Length); }
    }
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  {
      Response.Code = response.StatusCode;
      var nextPartitionKey = response.Headers["x-ms-continuation-NextPartitionKey"];
      var nextRowKey = response.Headers["x-ms-continuation-NextRowKey"];
      using (StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
      {
          Response.Data = stream.ReadToEnd();
          Response.NextPartitionKey = nextPartitionKey;
          Response.NextRowKey = nextRowKey;
      }
  }     
  return Response;
}

基本上我所做的是在您的HttpResponseData 对象中添加两个属性(NextPartitionKeyNextRowKey),并分别使用您从响应标头获得的nextPartitionKeynextRowKey 填充它。

您必须在代码中(处理响应的地方)检查这两个值中的任何一个是否不为空或不为空。非 null/空值表示存在更多实体。

如果是这种情况,那么您要做的就是修改 URL,将 NextPartitionKeyNextRowKey 值附加为查询字符串参数(有关详细信息,请参阅上面的链接)并再次发送请求。您将需要这样做,直到您将这两个值都作为空字符串或空字符串。

【讨论】:

  • 谢谢!您能否在上面的代码中展示如何使用这些延续标记?
  • 您能否编辑您的问题并包含 HttpHelper.GetForOdata() 的代码?
  • 两件事:1)不要链接到代码问题,而是发布完整的代码。如果有人编辑/删除链接的问题,您的问题将变得无关紧要。 2)我看到链接的问题正在使用ODatafilter.HttpHelper。我不确定它来自哪里。请相应地编辑您的问题并提供更多详细信息。它本身应该是完整的。
  • 用所需的代码更新了问题。谢谢!
  • 能否请您提供最新信息?谢谢!
猜你喜欢
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多