【问题标题】:Linq to DocumentDb, where clause on childLinq to DocumentDb,子句的 where 子句
【发布时间】:2023-03-08 06:27:01
【问题描述】:

在我目前正在进行的一个项目中,我们已经意识到我们不应该使用 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&lt;T&gt; 对象的方法会涉及大量代码,因为它需要将所有*.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

【问题讨论】:

  • 两种情况下生成的 SQL 查询是什么?我敢打赌,第二个创建了一个简单的WHERE 子句,而第一个创建了一个奇怪的子查询。顺便说一句,SQL 是类型安全的。参数化 SQL 查询也是类型安全的。这是类型不安全的字符串连接。
  • 不知道生成的SQL是什么样子的。我不知道如何确定。让我研究一下(今天晚些时候)。你的第二个陈述是什么意思?
  • 最坏的情况,你可以使用 Fiddler 来捕获发送到数据库的 HTTP 请求
  • 事实证明这几乎是不可能的...... Fiddler 没有显示任何查询流量。该代码不允许我检查生成的 SQL afaik。
  • 您还可以通过在 LINQ 查询上调用 toString() 来检查生成的 SQL。

标签: c# linq azure-cosmosdb


【解决方案1】:

已确认这是 SDK 的问题。已签入一个修复程序,并将随下一个 SDK 下降一起提供。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 2015-08-29
    • 1970-01-01
    相关资源
    最近更新 更多