简体   繁体   English

Linq to DocumentDb,关于子项的where子句

[英]Linq to DocumentDb, where clause on child

In a project i'm currently working on, we have come to realise that we should not use DocumentDb collections as if they are the equivalent of a table in f.ex SQL Server. 在我目前正在从事的项目中,我们已经意识到我们不应该像使用f.ex SQL Server中的表那样使用DocumentDb集合。 As a result, we are now persisting all of the entities, belonging to a single tenant in a single collection. 结果,我们现在将所有属于单个租户的实体都保留在一个集合中。

We already have lots of linq queries in our codebase which assume that each document type (aggregate root) is persisted in a dedicated collection. 我们的代码库中已经有很多linq查询,它们假定每种文档类型(聚合根)都保存在专用集合中。 In an attempt to make the transition painless, i set out to refactor our data access object, so that its api continues to reason about aggregate roots, and deal with the single collection vs dedicated collections in it's implementation. 为了使过渡顺利进行,我着手重构我们的数据访问对象,以便其api继续推理聚合根,并在其实现中处理单个集合与专用集合。

My approach is to wrap an aggregate root in an Resource<T> object, which derives from Resource and exposes a Model property as well as a Type property. 我的方法是将聚合根包装在Resource<T>对象中,该对象从Resource派生并公开Model属性和Type属性。 I thought i would then be able to expose an IQueryable<T> to consuming code based on the following code: 我以为我可以根据以下代码将IQueryable<T>公开给使用代码:

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

Initial testing showed that this worked as planned and i confidently committed my changes. 初步测试表明,此操作按计划进行,我自信地做出了更改。 When doing functional testing however, we found that some queried models had all of their properties set to their default values (ie. null, 0, false, etc). 但是,在进行功能测试时,我们发现某些查询的模型的所有属性都设置为其默认值(即null,0,false等)。

I can reproduce the problem with the following code: 我可以使用以下代码重现该问题:

        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();

The results of the above queries are not the same!! 以上查询结果一样!!

  • Both queries return the same number of TModel instances . 这两个查询返回相同数量的TModel实例
  • Only the instances returned by the second example have their properties populated. 仅第二个示例返回的实例具有其属性。

In order for my refactoring to be successful, i need wrong to be ... right :) Falling back to SQL is not an option as we value type safety of linq. 为了使我的重构成功,我需要wrong ...正确:):由于我们重视linq的类型安全性,因此不能选择使用SQL。 Changing our approach to expose the Resource<T> objects would touch lots of code, as it requires all *.Property references to be substituted by *.Model.Property references. 改变我们的方法以暴露出Resource<T>对象将触摸大量的代码,因为它需要所有*.Property引用被1-3 *.Model.Property引用。

It seems an issue with the linq provider that is part of the DocumentDb client. 属于DocumentDb客户端的linq提供程序似乎存在问题。

We use Microsoft.Azure.DocumentDb version 1.4.1 我们使用Microsoft.Azure.DocumentDb版本1.4.1

Edit 2015-09-24 编辑2015-09-24

The generated SQL queries are: 生成的SQL查询为:

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

Also, this issue has been reported (and picked up) on GitHub here: https://github.com/Azure/azure-documentdb-net/issues/58 另外,此问题已在GitHub上报告(并捡到): https : //github.com/Azure/azure-documentdb-net/issues/58

This has been confirmed as a problem with the SDK. 已确认这是SDK的问题。 a fix has been checked in and will ship with the next SDK drop. 修复程序已签入,将随下一个SDK发行版一起提供。

in the interim you can use SQL, or change where you place the WHERE clauses. 在此期间,您可以使用SQL,或更改放置WHERE子句的位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM