Linq to DocumentDb,where子句
Linq to DocumentDb, where clause on child
在我目前正在进行的一个项目中,我们已经意识到我们不应该使用 DocumentDb 集合,就好像它们等同于 f.ex [=70= 中的 table ] 服务器。因此,我们现在将属于单个集合中的单个租户的所有实体持久化。
我们的代码库中已经有很多 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();
以上查询的结果不一样!!
- 两个查询 return 相同数量的
TModel
个实例。
- 只有第二个示例 return 的实例才会填充其属性。
为了让我的重构成功,我需要 wrong
是......正确的:) 退回到 SQL 不是一个选项,因为我们重视 linq 的类型安全。改变我们公开 Resource<T>
对象的方法会触及很多代码,因为它要求所有 *.Property
引用都被 *.Model.Property
引用替换。
DocumentDb 客户端中的 linq 提供程序似乎有问题。
我们使用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
这已被确认为 SDK 的问题。已签入修复程序并将随下一个 SDK 发布一起发布。
在此期间,您可以使用 SQL,或更改放置 WHERE 子句的位置。
在我目前正在进行的一个项目中,我们已经意识到我们不应该使用 DocumentDb 集合,就好像它们等同于 f.ex [=70= 中的 table ] 服务器。因此,我们现在将属于单个集合中的单个租户的所有实体持久化。
我们的代码库中已经有很多 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();
以上查询的结果不一样!!
- 两个查询 return 相同数量的
TModel
个实例。 - 只有第二个示例 return 的实例才会填充其属性。
为了让我的重构成功,我需要 wrong
是......正确的:) 退回到 SQL 不是一个选项,因为我们重视 linq 的类型安全。改变我们公开 Resource<T>
对象的方法会触及很多代码,因为它要求所有 *.Property
引用都被 *.Model.Property
引用替换。
DocumentDb 客户端中的 linq 提供程序似乎有问题。
我们使用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
这已被确认为 SDK 的问题。已签入修复程序并将随下一个 SDK 发布一起发布。
在此期间,您可以使用 SQL,或更改放置 WHERE 子句的位置。