我在我的应用程序中有一个常见的情况,我创建一个查询来获取所有实体,其中partitionkey是常量但rowkey应该在词法范围内(例如,只有以某些前缀开头的行):
//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获得一个关于我的功能不受支持的例外。有没有办法写这个以便它被支持?毕竟,我使用与查询完全相同的条件,只是包含在一个函数中......
答案 0 :(得分:17)
以下是凯文答案的概括。它做同样的事情,但适用于任何前缀字符串,而不仅仅是大卫在原始问题中询问的特定情况。
public static Expression<Func<MyEntity, bool>> HasPrefix(String prefix)
{
char lastChar = prefix[prefix.Length - 1];
char nextLastChar = (char)((int)lastChar + 1);
string nextPrefix = prefix.Substring(0, prefix.Length - 1) + nextLastChar;
return e => e.RowKey.CompareTo(prefix) >= 0 && e.RowKey.CompareTo(nextPrefix) < 0;
}
答案 1 :(得分:10)
如果将条件分解为函数,则函数需要返回表达式树而不是布尔值。我不知道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();