2010-10-11 69 views
0

我試圖從持續令牌使用分頁時從Azure表存儲獲取一些記錄。當訪問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

OK,我認爲有幾件事情會在這裏的。我認爲有一個邏輯缺陷。不應

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

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

其次,你必須非常小心哪些功能是湛藍的表查詢的支持。通常他們不是。我測試了.Substring().IndexOf(),並且它們在Azure Table查詢中不起作用,因此.ToInt64()工作的機率很小。

您也許能夠重新格式化這是

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

這可能不會產生一個非常高效的查詢,因爲Azure中可以感到困惑,如果你有一個基於分區鍵兩個過濾器,只是做一個表掃描。另一個選擇是不包含查詢的endTicks部分,並且當您處理結果時,當您到達一個分區鍵時,分區鍵大於結束滴答,請停止處理結果。

此外,您編寫的代碼不會基於continuation標記獲取所有項目,它只會獲取返回的第一組結果。我覺得你的最終代碼應該是這個樣子(未編譯,未經測試,我敢肯定,人們可以看到一些性能改進:

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; 

}

+0

你說得有個邏輯錯誤,但它應該已經:Convert.ToInt64(s.RowKey.Substring(0,s.RowKey.IndexOf(「_」))) 你也是對的延續令牌,如果我只是採取一些結果,那麼顯然將不會是一個連續的令牌 我會嘗試修復它,看看它是否工作。謝謝你的幫助!真的很感謝答覆 - 我花了整整一天。 – rksprst 2010-10-11 23:50:45

+0

I bel ieve分區範圍(如x 0替換。 – smarx 2010-10-12 01:14:40

+0

我一直聽到有關你可以和不能在引用分區鍵的查詢中使用(談論可能的表掃描會嚇壞我)。也許有人應該產生一個規範的參考,並把它放在視頻的某個地方......在這種情況下,它看起來純粹是學術,因爲無論如何它都是行鍵。 – knightpfhor 2010-10-12 01:37:22

相關問題