Выражение не поддерживается ошибка при доступе к таблицам Azure - PullRequest
0 голосов
/ 12 октября 2010

Я пытаюсь получить некоторые записи из хранилища таблиц 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;
    }

1 Ответ

1 голос
/ 12 октября 2010

ОК, я думаю, что здесь происходит несколько вещей. Один, я думаю, есть логический недостаток. Не должны

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, и когда вы обрабатываете результаты, когда вы получаете один из них, ключ раздела больше, чем конечные тики, останавливает обработку результатов.

Кроме того, ваш код в том виде, в котором он написан, не получит все элементы на основе токена продолжения, он просто получит первый набор результатов, которые будут возвращены. Я думаю, что ваш окончательный код должен выглядеть примерно так (не скомпилировано, не проверено, и я уверен, что люди могут увидеть некоторые улучшения производительности:

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;

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...