Azure表存储投影查询和未实现异常

And*_*ltz 2 azure azure-table-storage

我有一个 Person 类,并将其保存到 Azure 表存储中的表中。

我想使用以下查询之一来查询它:

var query = from getThis in _serviceContext.CreateQuery<PersonForSearch>(_tableName)
                        where getThis.Name.Contains(searchTerm)
                        select new Person
                        {
                            PartitionKey = getThis.PartitionKey, 
                            RowKey = getThis.RowKey,
                            Name = getThis.Name
                        };
Run Code Online (Sandbox Code Playgroud)

或者

CloudTableQuery<Person> query =
                 (from getThis in _serviceContext.CreateQuery<Person>(_tableName)
                  where getThis.Name.Contains(searchTerm)
                  select getThis).AsTableServiceQuery<Person>();
Run Code Online (Sandbox Code Playgroud)

无论使用哪一种,我都会收到以下错误,该错误出现在我用来循环查询结果的 foreach 循环上:

NotImplemented 未在指定资源上执行请求的操作。

我认为这可能是因为我的 Person 模型不是从 TableServiceEntity 继承的(我拒绝引入这种耦合 - 所以我用这个属性装饰它: [DataServiceKey("PartitionKey", "RowKey")] 并手动给出它是 PartitionKey 和 RowKey 属性。

因此,我尝试创建一个 DID 继承自 TableServiceEntity 的实体,这将允许我查询该表(正如您从查询中看到的,我唯一担心的属性是 Name)。

这个新实体如下:

class PersonForSearch : TableServiceEntity
{
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然而,这并没有解决问题。此错误是否涉及我在查询中使用的类以外的其他资源?

Igo*_*rek 5

这里有两个问题:

1) Azure 表存储不支持 Contains() 方法。这就是您收到未实现异常的原因。ATS 确实支持 string.Compare() 对字符串进行任何范围类型操作

2)为了有效检索数据,只能按PartitionKey或PartitionKey/RowKey组合进行搜索。任何其他查询都将导致错误或将完整表下载到客户端内存中(不记得是哪一个)。如果您的表很小,请通过删除“where”子句将其完全下载到内存中,然后使用 Linq for Objects 进行查询。如果很大,想办法与 PartitionKey 或 PartitionKey/RowKey 字段进行比较

如果我理解您想要正确执行的操作,那就是您正在尝试通过员工表进行部分字符串搜索。总体而言,对于进行基于字符串的搜索,ATS 并不是一个非常好的解决方案(除非这些是对 PartitionKey 或 PartitionKey/RowKey 字段进行“开头”搜索)。我强烈推荐Lucene.NET在云中进行基于文本的搜索。还有一个适用于 Lucene.NET 的Azure Directory API。或者切换到 SQL Azure

华泰

  • 在非 PK 或 RK 字段上搜索会起作用并且不会导致错误,但会导致 ATS 扫描整个表,效率非常低。 (3认同)