3

好的,所以我第一次在 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 表存储可以做到这一点吗?

谢谢,大卫

4

2 回答 2

2
  • Azure 表存储的 .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是,表服务不支持该方法,但您可以编写一个简单的方法来动态构建您的 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();
于 2016-04-11T02:58:21.450 回答
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 一起使用,效率会更高。我的表很小(最多几百条记录),所以这应该不是问题。

希望这可以帮助某人。

大卫

于 2013-05-16T13:05:22.100 回答