0

我试图在使用带有延续令牌的分页时从 Azure 表存储中获取一些记录。

我有以下代码:

public Stories SelectStory(DateTime start, DateTime end, string searchGuid)
{
  long startTicks = DateTime.MaxValue.Ticks - start.ToUniversalTime().Ticks;
  long endTicks = DateTime.MaxValue.Ticks - end.ToUniversalTime().Ticks;

  var stories = _ServiceContext.CreateQuery<Story>("Story").Where(s => Convert.ToInt64(s.RowKey.Substring(0, s.PartitionKey.IndexOf("_"))) > startTicks
         && Convert.ToInt64(s.RowKey.Substring(0, s.PartitionKey.IndexOf("_"))) < endTicks
         && s.RowKey == "story_" + searchGuid).Take(50);
  var query = stories as DataServiceQuery<Story>;
  var results = query.Execute();
  var response = results as QueryOperationResponse;

  Stories temp = new Stories();
  if(response.Headers.ContainsKey("x-ms-continuation-NextRowKey"))
  {
    temp.NextPartitionKey = response.Headers["x-ms-continuation-NextPartitionKey"];
    if (response.Headers.ContainsKey("x-ms-continuation-NextRowKey"))
    {
      temp.NextRowKey = response.Headers["x-ms-continuation-NextRowKey"];
    }
  }
  temp.List = results.ToList();

  return temp;
}

但我收到以下错误:

 The expression (((ToInt64([10007].RowKey.Substring(0, [10007].PartitionKey.IndexOf("_"))) > 2521167043199999999) And (ToInt64([10007].RowKey.Substring(0, [10007].PartitionKey.IndexOf("_"))) < 2521154083199999999)) And ([10007].RowKey == "story_9")) is not supported. 

我不确定为什么不允许表达。有谁知道如何改变它以使其正常工作?

谢谢!

编辑:新代码(没有错误,但没有选择数据 - 即使我知道它存在):

public Stories SelectStory(DateTime start, DateTime end, string searchGuid)
    {
        long startTicks = DateTime.MaxValue.Ticks - start.ToUniversalTime().Ticks;
        long endTicks = DateTime.MaxValue.Ticks - end.ToUniversalTime().Ticks;

        var strStart = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - startTicks, "00000000-0000-0000-0000-000000000000");
        var strEnd = string.Format("{0:10}_{1}", DateTime.MaxValue.Ticks - endTicks, "00000000-0000-0000-0000-000000000000");

        var stories = _ServiceContext.CreateQuery<Story>("Story").Where(
                        s => s.RowKey.CompareTo(strStart) < 0
                            && s.RowKey.CompareTo(strEnd) > 0
                           //s.RowKey.CompareTo(startTicks.ToString() + "_") > 0
                     //&& s.RowKey.CompareTo(endTicks.ToString() + "_00000000-0000-0000-0000-000000000000") > 0
                     && s.PartitionKey == ("story_" + searchGuid)
                     ).Take(50);
        var query = stories as DataServiceQuery<Story>;
        var results = query.Execute();
        var response = results as QueryOperationResponse;

        Stories temp = new Stories();
        if(response.Headers.ContainsKey("x-ms-continuation-NextRowKey"))
        {
            temp.NextPartitionKey = response.Headers["x-ms-continuation-NextPartitionKey"];
            if (response.Headers.ContainsKey("x-ms-continuation-NextRowKey"))
            {
                temp.NextRowKey = response.Headers["x-ms-continuation-NextRowKey"];
            }
        }
        temp.List = results.ToList();

        return temp;
    }
4

1 回答 1

1

好的,我认为这里发生了一些事情。我认为有一个逻辑缺陷。不应该

Convert.ToInt64(s.RowKey.Substring(0, s.PartitionKey.IndexOf("_")))

Convert.ToInt64(s.PartitionKey.Substring(0, s.PartitionKey.IndexOf("_")))

其次,您需要非常小心 azure 表查询支持哪些功能。一般来说,他们不是。我已经测试过.Substring().IndexOf()它们在 Azure 表查询中不起作用,所以.ToInt64()工作的机会很小。

您也许可以将其重新格式化为

s => s.PartitionKey > startTicks.ToString() + "_"
&& s.PartitionKey < endTicks.ToString() + "_"
&& s.RowKey == "story_" + searchGuid

这可能不会生成非常有效的查询,因为如果您有两个基于分区键的过滤器并且只进行表扫描,Azure 可能会感到困惑。另一种选择是不包括查询的 endTicks 部分,当您处理结果时,当您到达一个分区键大于 end ticks 时,停止处理结果。

此外,您编写的代码不会基于延续令牌获得所有项目,它只会获得返回的第一组结果。我认为您的最终代码应该看起来像这样(未编译,未经测试,我相信人们可以看到一些性能改进:

private class ListRowsContinuationToken
{
    public string NextPartitionKey { get; set; }
    public string NextRowKey { get; set; }
}

public Stories SelectStory(DateTime start, DateTime end, string searchGuid)
{
    long startTicks = DateTime.MaxValue.Ticks - start.ToUniversalTime().Ticks;
    long endTicks = DateTime.MaxValue.Ticks - end.ToUniversalTime().Ticks;

var stories = _ServiceContext.CreateQuery<Story>("Story").Where(s => s.PartitionKey > startTicks.ToString() + "_"
                && s.PartitionKey < endTicks.ToString() + "_"
                && s.RowKey == "story_" + searchGuid).Take(50);

var query = stories as DataServiceQuery<Story>;

Stories finalList = new Stories();

var results = query.Execute();

ListRowsContinuationToken continuationToken = null;
bool reachedEnd = false;

do
{
    if ((continuationToken != null))
    {
        servicesQuery = servicesQuery.AddQueryOption("NextPartitionKey", continuationToken.NextPartitionKey);

        if (!string.IsNullOrEmpty(continuationToken.NextRowKey))
        {
            servicesQuery.AddQueryOption("NextRowKey", continuationToken.NextRowKey);
        }
    }

    var response = (QueryOperationResponse<T>)query.Execute();

    foreach (Story result in response)
    {
        if (result.PartitionKey < endTicks.ToString())
        {
            finalList.AddRange(result);
        }
        else
        {
            reachedEnd = true;
        }
    }

    if (response.Headers.ContainsKey("x-ms-continuation-NextPartitionKey"))
    {
        continuationToken = new ListRowsContinuationToken
        {
            NextPartitionKey = response.Headers["x-ms-continuation-NextPartitionKey"]
        };

        if (response.Headers.ContainsKey("x-ms-continuation-NextRowKey"))
        {
            continuationToken.NextRowKey = response.Headers["x-ms-continuation-NextRowKey"];
        }
    }
    else
    {
        continuationToken = null;
    }

} while (continuationToken != null && reachedEnd == false);

return finalList;

}

于 2010-10-11T22:20:02.943 回答