【问题标题】:The expression is not supported error when accessing Azure Tables访问 Azure 表时出现不支持表达式错误
【发布时间】:2011-04-23 23:56:46
【问题描述】:

我在使用带有延续令牌的分页时尝试从 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;
    }

【问题讨论】:

    标签: c# azure azure-storage azure-table-storage


    【解决方案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;
    

    }

    【讨论】:

    • 你是对的,有一个逻辑错误,但它应该是:Convert.ToInt64(s.RowKey.Substring(0, s.RowKey.IndexOf("_"))) 你'关于延续令牌也是正确的,如果我只得到一些结果,那么显然不会有延续令牌。我现在要尝试修复它,看看它是否有效。谢谢您的帮助!非常感谢您的回复 - 我已经花了一整天的时间。
    • 我相信分区范围(如 x 0。
    • 我不断听到关于在引用分区键的查询中可以使用和不能使用什么的相互矛盾的消息(谈论可能的表扫描让我大吃一惊)。也许有人应该制作一个规范的参考并将其放在视频中的某个地方......在这种情况下它似乎纯粹是学术性的,因为它无论如何都应该是行键。
    • 我很好奇 RowKey 怎么可以是 {numberofticks}_{something else} 和 story_{a guid}?
    • RowKey 是 {max ticks - ticks of data}_{guid},分区键是 story_{guid}。我还更新了帖子以反映我的尝试。 @smarx 你是对的,我不得不使用 CompareTo 因为 是不允许的。但它仍然不起作用 - 没有选择任何元素。
    猜你喜欢
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2019-12-17
    • 1970-01-01
    相关资源
    最近更新 更多