Как запросить хранилище таблиц azure с помощью одинарной кавычки в PartitionKey
Я переношу некоторый код из старого клиента хранилища таблиц azure в последнюю версию и столкнулся с проблемой, которая поставила меня в тупик: я не могу отправить запрос с одной кавычкой в ключе раздела, не получив 400 неверных запросов. Например:
public class TestEntity : TableEntity
{
public string TestProperty { get; set; }
}
public class StorageTester
{
public static void TestInsert()
{
CloudStorageAccount acct = CloudStorageAccount.DevelopmentStorageAccount;
CloudTableClient client = acct.CreateCloudTableClient();
CloudTable table = client.GetTableReference("testtable");
table.CreateIfNotExists();
// insert a test entity -- this works fine
TestEntity entity = new TestEntity();
entity.PartitionKey = "what's up";
entity.RowKey = "blah";
entity.TestProperty = "some dataz";
TableOperation op = TableOperation.Insert(entity);
table.Execute(op);
// now query the entity -- explicit query constructed for clarity
string partitionFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "what's up");
string rowFilter = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, "blah");
string finalFilter = TableQuery.CombineFilters(partitionFilter, TableOperators.And, rowFilter);
TableQuery<TestEntity> query = new TableQuery<TestEntity>().Where(finalFilter);
// THIS THROWS 400 ERROR, does not properly encode partition key
var entities = table.ExecuteQuery(query, new TableRequestOptions { RetryPolicy = new NoRetry() });
entity = entities.FirstOrDefault();
}
}
Я перепробовал все... Я попытался явно задать свойство FilterString в Tabletquery, но оно выполняет кодировку URL после установки этого свойства, поэтому если я заменю одиночную кавычку на %27, то % получит дважды сбежал.
Есть ли у кого-нибудь обходной путь, который позволил бы мне использовать новую библиотеку хранения таблиц, не возвращаясь к старой библиотеке StorageClient? Обратите внимание, что у меня уже есть много данных в существующей базе данных, поэтому такие решения, как "просто не используйте одиночные кавычки в запросах", были бы абсолютным крайним средством, поскольку это потребовало бы сканирования и обновления каждой отдельной записи в каждой существующей таблице-задача обслуживания, которую я хотел бы избежать.
2 ответа:
Вам нужно экранировать одинарную кавычку, но только при фильтрации (путем добавления одинарной кавычки перед исходной одинарной кавычкой):
string partitionFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "what''s up");
Это происходит потому, что
GenerateFilterCondition
иCombineFilters
превращают фильтр в простую строку (формат OData):(PartitionKey eq 'what''s up') and (RowKey eq 'blah')
Более безопасным способом использования фильтров было бы следующее:
string partitionFilter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey.Replace("'", "''"));
Я использую хранилище Windows Azure 7.0.0, и вы можете использовать запрос Linq, чтобы вам не нужно было экранировать одинарные кавычки:
// Get the cloudtable ... var table = GetCloudTable(); // Create a query: in this example I use the DynamicTableEntity class var query = cloudTable.CreateQuery<TestEntity>() .Where(d => d.PartitionKey == "what's up" && d.RowKey == "blah"); var entities = query.ToList();
Если вы проверите свойство
query.FilterString
, то увидите, что единственная цитата была экранирована:"(PartitionKey eq 'what' s up') и (RowKey eq 'blah') "