8

我正在将一些代码从较旧的 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();

    }
}

我已经尝试了一切......我尝试显式设置 TableQuery 的 FilterString 属性,但它在设置该属性后执行 URL 编码,所以如果我用 %27 替换单引号,% 会被双重转义。

有没有人有一种解决方法可以让我使用新的表存储库而不回退到旧的 StorageClient 库?请注意,我在现有数据库中已经有很多数据,因此像“不要在查询中使用单引号”这样的解决方案绝对是最后的手段,因为它需要扫描和更新每个现有表中的每条记录-- 我想避免的维护任务。

4

2 回答 2

5

您需要转义单引号,但仅在过滤时(通过在原始单引号前添加单引号):

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("'", "''"));
于 2012-11-29T00:06:12.660 回答
2

我使用的是Windows Azure Storage 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')”

于 2016-04-10T23:20:18.310 回答