我正在尝试使用带有延续令牌的分页从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;
}
答案 0 :(得分:1)
好的,我认为这里有几件事情。我认为存在一个逻辑缺陷。不应该
Convert.ToInt64(s.RowKey.Substring(0, s.PartitionKey.IndexOf("_")))
是
Convert.ToInt64(s.PartitionKey.Substring(0, s.PartitionKey.IndexOf("_")))
其次,您需要非常小心天蓝色表查询支持哪些功能。一般来说,他们不是。我已经测试了.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;
}