从 Azure Table 存储 OData 筛选器查询中读取超过 1000 行?

Read more than 1000 rows from Azure Table Storage OData filter query?

我们如何从 Azure Table 存储中读取超过 1000 行?这是我用于从 Table 存储读取数据的代码,它只检索 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 header 值。如何在下一个请求中传递这些值?

                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();
                    }
                }

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

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

您可以在此处了解有关 Azure Table 存储中分页的更多信息: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)并用 nextPartitionKey 和 [=17= 填充它] 分别从响应头中得到。

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

如果是这种情况,那么您需要做的是通过附加 NextPartitionKeyNextRowKey 值作为查询字符串参数来修改 URL(请参阅 link 上面的详细信息)并再次发送请求。您将需要执行此操作,直到您将这两个值都作为 null 或空字符串。