Linq到DocumentDb,关于子

时间:2015-09-22 20:36:05

标签: c# linq azure-cosmosdb

在我目前正在开展的项目中,我们已经意识到我们不应该使用DocumentDb集合,就好像它们相当于f.ex SQL Server中的表。因此,我们现在将属于单个租户的所有实体保留在一个集合中。

我们的代码库中已经有很多linq查询,它们假设每个文档类型(聚合根)都保存在专用集合中。为了使转换无痛,我开始重构我们的数据访问对象,以便它的api继续推理聚合根,并处理单个集合与其实现中的专用集合。

我的方法是将聚合根包装在Resource<T>对象中,该对象派生自Resource并公开Model属性以及Type属性。我想我可以根据以下代码公开IQueryable<T>消费代码:

        return _client.CreateDocumentQuery<Resource<TModel>>(_collection.DocumentsLink)
            .Where(x => x.Type == typeof(TModel).Name)
            .Select(x => x.Model);

初步测试表明,这是按计划进行的,我自信地承诺了我的更改。然而,在进行功能测试时,我们发现一些查询模型的所有属性都设置为默认值(即null,0,false等)。

我可以使用以下代码重现该问题:

        var wrong = _client.CreateDocumentQuery<Resource<TModel>>(_collection.DocumentsLink)
            .Where(x => x.Type == typeof(TModel).Name)
            .Select(x => x.Model)
            .Where(x => !x.IsDeleted)
            .ToArray();

        var correct = _client.CreateDocumentQuery<Resource<TModel>>(_collection.DocumentsLink)
            .Where(x => x.Type == typeof(TModel).Name)
            .Where(x => !x.Model.IsDeleted)
            .Select(x => x.Model)
            .ToArray();

以上查询的结果相同!!

  • 两个查询都返回相同数量的TModel个实例
  • 只有第二个示例返回的实例才会填充其属性。

为了使我的重构成功,我需要wrong为...正确:)回归到SQL不是一个选项,因为我们重视linq的类型安全性。更改我们公开Resource<T>对象的方法会涉及大量代码,因为它要求所有*.Property引用都被*.Model.Property引用替换。

linq提供程序似乎是DocumentDb客户端的一部分。

我们使用Microsoft.Azure.DocumentDb 1.4.1版

编辑2015-09-24

生成的SQL查询是:

  • 正确:{"query":"SELECT VALUE root.Model FROM root WHERE ((root.Type = \"DocumentType\") AND (NOT root.Model.IsDeleted)) "}
  • 错误:{"query":"SELECT * FROM root WHERE ((root.Type = \"DocumentType\") AND (NOT root.Model.IsDeleted)) "}

此外,此问题已在GitHub上报告(并已选中):https://github.com/Azure/azure-documentdb-net/issues/58

1 个答案:

答案 0 :(得分:0)

这已被确认为SDK的问题。已修复已修复的修补程序,并将随附下一个SDK drop。

在此期间您可以使用SQL,或更改WHERE子句的放置位置。