1

我正在尝试做一些看起来非常简单的事情,但是当我想让它变得更有活力时,我遇到了巨大的困难。

    Expression<Func<TableServiceEntity, bool>> predicate = (e) => e.PartitionKey == "model" && (e.RowKey == "home" || e.RowKey == "shared");

context.CreateQuery<TableServiceEntity>(tableName).Where(predicate);

我想传递一个 rowKey 数组,而不必对谓词进行硬编码。

当我尝试构建表达式树时,我收到一个不受支持的异常,我认为它不支持作为表达式树的一部分进行调用。

有人知道如何完全按照谓词构建和表达树以避免不支持的异常吗?

提前谢谢你

4

3 回答 3

2

因此,您可以使用以下内容动态构建查询(取自PhluffyFotos示例):

        Expression<Func<PhotoTagRow, bool>> search = null;
        foreach (var tag in tags)
        {
            var id = tag.Trim().ToLowerInvariant();

            if (String.IsNullOrEmpty(id))
            {
                continue;
            }

            Expression<Func<PhotoTagRow, bool>> addendum = t => t.PartitionKey == id;

            if (search == null)
            {
                search = addendum;
            }
            else
            {
                search = Expression.Lambda<Func<PhotoTagRow, bool>>(Expression.OrElse(search.Body, addendum.Body), search.Parameters);
            }
        }

现在,一旦你有了“搜索”,你就可以将它作为谓词传递给你的 Where 子句。

但是,我想说服你不要这样做。我正在回答您的问题,但告诉您执行多个 '|' 是个坏主意 表存储中的 OR 子句。原因是至少在今天,这些查询无法优化,它们会导致全表扫描。对于任何不平凡的数据量,性能将是可怕的。此外,如果您像这样动态地构建您的谓词,您将面临破坏 URL 限制的风险(请记住这一点)。

PhluffyFotos 中的这段代码展示了如何,但这实际上是一种不好的做法(我知道,我写了它)。它确实应该被优化为分别并行运行每个 OR 子句。这才是你真正应该做的。AND 子句可以,但 OR 子句应该并行化(使用 PLINQ 或 TPL)并且您应该汇总结果。它会快得多。

HTH。

于 2011-05-12T13:22:55.110 回答
1

我相信 HTH 关于这种执行全表扫描的查询的说法从我阅读的文档中是不正确的。Azure 将执行 PARTITION 扫描而不是 TABLE 扫描,这在性能上有很大差异。

于 2011-10-11T21:24:20.573 回答
0

这是我的解决方案,请同时阅读 HTH 的回答,他指出这不是最佳实践。

var parameter = Expression.Parameter(typeof(TableServiceEntity), "e");

var getPartitionKey = typeof(TableServiceEntity).GetProperty("PartitionKey").GetGetMethod();
var getRowKey = typeof(TableServiceEntity).GetProperty("RowKey").GetGetMethod();

var getPartition = Expression.Property(parameter, getPartitionKey);
var getRow = Expression.Property(parameter, getRowKey);

var constPartition = Expression.Constant("model", typeof(string));
var constRow1 = Expression.Constant("home", typeof(string));
var constRow2 = Expression.Constant("shared", typeof(string));

var equalPartition = Expression.Equal(getPartition, constPartition);
var equalRow1 = Expression.Equal(getRow, constRow1);
var equalRow2 = Expression.Equal(getRow, constRow2);

var and = Expression.AndAlso(equalPartition, Expression.OrElse(equalRow1, equalRow2));

return Expression.Lambda<Func<TableServiceEntity, bool>>(and, parameter);
于 2011-05-14T10:35:40.910 回答