Azure表存储:如何创建动态where子句?

时间:2013-05-16 12:32:05

标签: azure azure-storage azure-table-storage

好的,我在ASP.NET MVC 3应用程序中第一次使用Azure表存储。

我有一个表实体,其用户ID为RowKey。我有一个用户ID列表,需要获取具有其中一个用户ID的所有实体。

在传统的SQL中,您可以动态添加到where子句中的简单OR语句:

select * from blah
where userID = '123' or userID = '456' or userID = '789'

但我在Azure SDK中找不到相应的内容。

Azure Table Storage是否可以实现这一目标?

谢谢, 大卫

2 个答案:

答案 0 :(得分:1)

好的,有点挖掘我找到了答案。

您可以使用此处的语法构建where过滤器:http://msdn.microsoft.com/en-us/library/windowsazure/ff683669.aspx

因此,对于我的小例子,它最终看起来像这样:

我有一个以逗号分隔的ID字符串发送到此方法

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["TableStorageConnectionString"]);

CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable table = tableClient.GetTableReference("Blah");

string[] split = IDs.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

string filter = null;
for (int i = 0; i < split.Length; i++)
{
    filter += " RowKey eq '" + split[i] + "' ";
    if (i < split.Length - 1)
        filter += " or ";
}

TableQuery<Blah> rangeQuery = new TableQuery<Blah>().Where(filter);
var result = table.ExecuteQuery(rangeQuery);

结果列出了我需要的好东西。

要记住的一件事是你不想在一个非常大的表上使用它,因为我只获得了导致表扫描的RowKey。如果同时使用PartitionKey和RowKey,则效率更高。我的表非常小(最多几百条记录)所以它不应该成为一个问题。

希望这有助于某人。

大卫

答案 1 :(得分:1)

  • Azure Table Storage的.Net客户端具有生成和组合过滤器的功能。

这样你就可以像那样编写过滤器表达式

string[] split = IDs.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
string mainFilter = null;
foreach (var id in split)
{
    var filter = TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, id);
    mainFilter = mainFilter != null ? TableQuery.CombineFilters(mainFilter, TableOperators.And, filter) : filter;
}

var rangeQuery = new TableQuery<Blah>().Where(mainFilter);
var result = table.ExecuteQuery(rangeQuery);

不幸的是Contains方法不是supported by the Table Service,但您可以编写一个简单的方法来动态构建您的linq查询:

public static class ContainsExtension
{
    public static Expression<Func<TEntity, bool>> Contains<TEntity,
        TProperty>(this IEnumerable<object> values,
        Expression<Func<TEntity, TProperty>> expression)
    {
        // Get the property name
        var propertyName = ((PropertyInfo)((MemberExpression)expression.Body).Member).Name;

        // Create the parameter expression
        var parameterExpression = Expression.Parameter(typeof (TEntity), "e");

        // Init the body
        Expression mainBody = Expression.Constant(false);

        foreach (var value in values)
        {
            // Create the equality expression
            var equalityExpression = Expression.Equal(
                Expression.PropertyOrField(parameterExpression, propertyName),
                Expression.Constant(value));

            // Add to the main body
            mainBody = Expression.OrElse(mainBody, equalityExpression);
        }

        return Expression.Lambda<Func<TEntity, bool>>(mainBody, parameterExpression);
    }
}

这样您就可以轻松构建动态查询:

var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["TableStorageConnectionString"]);

var tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference("Blah");
var split = IDs.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

// Create a query: in this example I use the DynamicTableEntity class
var query = table.CreateQuery<DynamicTableEntity>()
        .Where(split.Contains((DynamicTableEntity d) => d.RowKey));

// Execute the query
var result = query.ToList();