我在应用程序中经常遇到这样的情况:我创建查询以获取所有分区键为常数但行键应在词法范围内的实体(例如,仅以某些前缀开头的行):

//query to get all entities in partition "KnownPartition" where RowKey starts with "Prefix_"
CloudTableQuery<MyEntity> query =
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName)
     where e.PartitionKey == "KnownPartition"
           && e.RowKey.CompareTo("Prefix_") > 0
           && e.RowKey.CompareTo("Prefix`") <= 0 // ` is '_' + 1
     select e).AsTableServiceQuery();

我必须使用CompareTo,因为这种查询不支持诸如StartsWith之类的字符串函数。这行得通,但条件很难阅读且重复很多。因此,与其编写大量具有这种难以理解的条件的查询,不如创建一个“内联”它的函数:
public static Boolean HasPrefix(this String rowKey, String prefix)
{
    return rowKey.CompareTo(prefix + '_') > 0 && rowKey.CompareTo(prefix + '`') <= 0;
}

CloudTableQuery<MyEntity> query =
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName)
     where e.PartitionKey == "KnownPartition" && e.RowKey.HasPrefix("Prefix")
     select e).AsTableServiceQuery();

但是,当我运行它时,我从Azure收到一个异常,提示我的功能不受支持。有什么办法可以编写该代码以使其受支持吗?毕竟,我使用与查询完全相同的条件,只是包裹在一个函数中...

最佳答案

如果将条件分解为一个函数,则该函数需要返回一个表达式树而不是 bool 值。我不知道LINQ查询语法是否支持此功能,但是您可以使用以下方法语法来做到这一点:

public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix)
{
    return e => e.RowKey.CompareTo(prefix + '_') > 0 && e.RowKey.CompareTo(prefix + '`') <= 0;
}

CloudTableQuery<MyEntity> query =
    (from e in tableServiceContext.CreateQuery<MyEntity>(tableName)
    where e.PartitionKey == "KnownPartition"
    select e)
    .Where(HasPrefix("Prefix"))
    .AsTableServiceQuery();

关于c# - 方法中包装了常用条件的Azure表存储范围查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12958848/

10-11 22:30
查看更多