在我目前正在开展的项目中,我们已经意识到我们不应该使用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版
生成的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
答案 0 :(得分:0)
这已被确认为SDK的问题。已修复已修复的修补程序,并将随附下一个SDK drop。
在此期间您可以使用SQL,或更改WHERE子句的放置位置。