我需要在Azure Tables的单个分区中选择多个行以供稍后更新。由于它们都具有相同的PartitionKey,如何构造我的查询以选择多个RowKeys?
我对原始(在线)查询应该是什么样的内容感兴趣,如果可能的话,我也对Linq查询感兴趣。
我自己尝试了这个并开始使用此查询:
var results = from c in _ServiceContext.ForumThreadTable
where(
(
(c.RowKey == rk) ||
(c.RowKey == "n1q") ||
(c.RowKey == "gm1w") ||
(c.RowKey == "fm1e") ||
(c.RowKey == "zbm1r") ||
(c.RowKey == "km1te1") ||
(c.RowKey == "jm1ye1") ||
(c.RowKey == "hm1u") ||
(c.RowKey == "gm1i") ||
(c.RowKey == "fm1te1") ||
(c.RowKey == "d4m1ye1") ||
(c.RowKey == "bm1u") ||
(c.RowKey == "bm1i") ||
(c.RowKey == "bm1o") ||
(c.RowKey == "bp1p")
) &&
c.PartitionKey == pk )
select c;
我的查询看起来像这样(来自fiddler)
GET http://127.0.0.1:10002/devstoreaccount1/ForumThreadTable()?$filter=(((((((((((((((RowKey%20eq%20'0634205427898279774')%20or%20(RowKey%20eq%20'n1q'))%20or%20(RowKey%20eq%20'gm1w'))%20or%20(RowKey%20eq%20'fm1e'))%20or%20(RowKey%20eq%20'zbm1r'))%20or%20(RowKey%20eq%20'km1te1'))%20or%20(RowKey%20eq%20'jm1ye1'))%20or%20(RowKey%20eq%20'hm1u'))%20or%20(RowKey%20eq%20'gm1i'))%20or%20(RowKey%20eq%20'fm1te1'))%20or%20(RowKey%20eq%20'd4m1ye1'))%20or%20(RowKey%20eq%20'bm1u'))%20or%20(RowKey%20eq%20'bm1i'))%20or%20(RowKey%20eq%20'bm1o'))%20or%20(RowKey%20eq%20'bp1p'))%20and%20(PartitionKey%20eq%20'GUIDeec4550c-a3fd-472b-9b7d-c79fae664415') HTTP/1.1
User-Agent: Microsoft ADO.NET Data Services
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 2.0;NetFx
x-ms-version: 2009-09-19
x-ms-date: Mon, 20 Sep 2010 02:49:48 GMT
Authorization: SharedKeyLite devstoreaccount1:MINFtQhWqbnYhn1spDGTGvPmNmW24YNzOeqBBtOletU=
Accept: application/atom+xml,application/xml
Accept-Charset: UTF-8
Host: 127.0.0.1:10002
这是我的错误:
"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>
<error xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\">
<code>InvalidInput</code>
<message xml:lang=\"en-US\">One of the request inputs is not valid.</message>
</error>"
我认为它可能需要对我拥有的RowKey条件的数量做更多的事情,而不是语法......但我愿意尝试任何事情。
谢谢!
答案 0 :(得分:2)
这与我们在Lokad.Cloud中所做的类似。我记得你可以毫无问题地以这种方式选择最多100行。您可以查看source code for the details并重复使用整个开源项目或仅重用您喜欢的部分。
以下是语法生成的样子:
public IEnumerable<CloudEntity<T>> Get<T>(string tableName, string partitionKey, IEnumerable<string> rowKeys)
{
Enforce.That(() => tableName);
Enforce.That(() => partitionKey);
Enforce.That(!partitionKey.Contains("'"), "Incorrect char in partitionKey.");
var context = _tableStorage.GetDataServiceContext();
foreach (var slice in rowKeys.Slice(MaxEntityTransactionCount))
{
// work-around the limitation of ADO.NET that does not provide a native way
// of query a set of specified entities directly.
var builder = new StringBuilder();
builder.Append(string.Format("(PartitionKey eq '{0}') and (", HttpUtility.UrlEncode(partitionKey)));
for (int i = 0; i < slice.Length; i++)
{
// in order to avoid SQL-injection-like problems
Enforce.That(!slice[i].Contains("'"), "Incorrect char in rowKey.");
builder.Append(string.Format("(RowKey eq '{0}')", HttpUtility.UrlEncode(slice[i])));
if (i < slice.Length - 1)
{
builder.Append(" or ");
}
}
builder.Append(")");
foreach(var entity in GetInternal<T>(context, tableName, builder.ToString()))
{
yield return entity;
}
}
}
但是,请记住,表操作不会优化此操作,导致性能欠佳(表存储不使用此操作的索引)。这是一个向Microsoft报告的错误,预计很快就会修复。
答案 1 :(得分:1)
您是否有关于此错误修复的进展的任何更新。 Azure表存储现在是否使用索引执行此类查询(在单个分区上使用OR操作的多个rowkey)?