【问题标题】:oData v4 - ordering outer entity on property in related one-to-many entitiesoData v4 - 对相关一对多实体中的属性排序外部实体
【发布时间】:2019-12-17 09:01:59
【问题描述】:

我有一个具有一对多关系的 oData 模型,例如 person->addresses 和 person->driving-licences。我希望能够根据地址实体和驾驶执照实体中的属性对结果集进行排序。由于可能有多个地址,我最初会根据名为IsPrimary 的属性从地址集中选择一个项目。由于可能有多个驾驶执照,我会选择“英国”驾驶执照。这可能吗?

我希望我可以这样做:

/people?$expand=addresses($filter=isPrimary eq true),drivinglicences($filter=country eq 'UK')&$orderby=addresses/postcode,drivinglicences/active

不幸的是,我收到以下错误:

“在 URI 中指定的查询无效。属性 'isPrimary' 的属性访问的父值不是单个值。属性访问只能应用于单个值。”

有谁知道规范是否支持我尝试做的事情?还是我的查询有问题?或者是否是 .NET 库的问题。

我正在使用: Microsoft.AspNet.OData - 7.2.3

非常感谢。

【问题讨论】:

  • 您愿意对 API 进行更改吗?正如stackoverflow.com/a/55324393/1690217 中所讨论的,规范中不支持此功能,您可以过滤单例导航属性,但不能过滤集合
  • 请用一两个您想过滤的其他关系或字段示例更新您的问题,这样我可以确保我的建议解决方案可行
  • 感谢您的回复。我已经用额外的关系更新了帖子。希望这能传达我正在尝试做的事情。我愿意对 API 进行更改。当您说规范中不支持它时-您对此有参考吗?我在规范中找不到任何明确的内容。 :)
  • 我已经发布了一个答案,尽管它并没有比以前的解决方案更有帮助。归根结底,要实现这些类型的排序,您将必须实现一个自定义端点,这是一半的乐趣。尽管 OData 允许非常彻底的查询语法,但并不期望每个 OData 查询都只使用 CRUD 端点,有时查询会比结果集本身更多的字节数。尝试实现自定义端点,或修改您的客户端,以便在客户端而不是服务器上完成排序......这当然意味着您应该有一个好的过滤器。

标签: asp.net odata


【解决方案1】:

您在此处看到的是设计使然,或者说不受规范支持,错误消息甚至突出显示了唯一支持的表达式类型:

URI 中指定的查询无效。属性“isPrimary”的属性访问的父值不是单个值。属性访问只能应用于单个值。

所以最简单的解决方案是修改 API 以包含一个绑定到 people 集合的 Function,该集合直接应用 $filter$order,或者一个 Function 以新的 shape 形式返回数据,该形状可能只有一个单一的 PrimaryAddress 属性。如何在此结果中包含驾驶执照取决于您,它甚至可以是函数的参数,也许您的人员控制器具有带有此签名的可查询函数:

[EnableQuery]
public IHttpActionResult WithLicences(string countryCode)

然而,这超出了 OP 关于特定语法支持的问题的范围


虽然这似乎是一个重要功能,但我们必须记住 $select (Projection) 和 $filter 在不同的时间点进行评估,OData 查询紧随其后与 SQL 类似的执行顺序,但是过滤条件和 $orderby 是分开评估的,结果集的投影是要应用的最后一个评估。

  • 由于 $filter 和 $orderby 是独立应用的,这两个概念甚至都不知道另一个概念,因此两者都不能引用或假设在另一个之前应用。

您可以通过在$orderby 和/或$filter 中指定一个未包含在$select 中的字段来证明这一点,您甚至可以引用未包含在$expand 中的单例导航字段和查询将正确评估。

OData 规范类似于法律文件,要正确理解和应用它,我们需要了解作者的初衷。我们可以从Addressing Entities的早期上市得到一个初步的了解

寻址实体描述了函数,这些函数可以绑定到集合或返回单个实体或实体集合的实体

通过允许应用自定义函数的特殊规定,作者正在鼓励 API 设计人员为其资源端点提供自然扩展,以促进执行预先确定的查询,否则这些查询可能很复杂或用纯 OData 查询语法表示有问题。

换句话说,我们鼓励定制我们的 API 以使它们更容易被最终进程使用,并指导使用开发者充分利用 API,他们不应该从一开始就发现一切校长。

要在纯 SQL 中实现 OP 类型的查询,仍然需要嵌套查找、CTE 或自连接...高级语法。在 OData v4 中,规范不提供针对路径表达式($orderby 派生自)集合中特定项目的语法

5.1.1.15 Path Expressions
请求 URL 所寻址的资源集的实体类型的属性和导航属性可以用作操作数或函数参数,如前面的示例所示。

可以通过与资源路径中相同的语法使用复杂属性的属性,即通过指定复杂属性的名称,后跟正斜杠 (/) 和复杂属性的属性名称,等等开,

可以通过指定导航属性来使用与目标基数 0..1 或 1 相关的实体的属性和导航属性,后跟正斜杠 (/) 和相关实体的属性名称,依此类推开。

如果复杂属性为 null,或者没有实体相关(在目标基数为 0..1 的情况下),则其值及其组件的值被视为 null。

RE:我在规范中找不到任何明确的内容。 :)

这正是 OData 规范的内容,规范没有列出不支持的内容,只列出了应该支持的内容。所以通过省略,如果你找不到关于如何做 something 的参考,那么 something 不需要被支持。

简介 http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_Introduction ... 该规范定义了一组推荐的(但不是必需的)规则,用于构建 URL 以识别 OData 服务公开的数据和元数据以及一组保留的 URL 查询字符串运算符,如果被 OData 服务接受,则必须按照本文档的要求实施。

这一直在 5 月线程中进行的持续讨论中,最近 https://stackoverflow.com/a/55324393/1690217 许多人抱怨这无疑是数据访问平台的基本特征,但重要的是要尊重 OData 平台的初衷并通过提供适合我们业务领域的定制端点来保持我们的 API 简单。

【讨论】:

  • 真棒,彻底的回应。谢谢。正是我所追求的。我将看看使用自定义函数的 api 修改,看看我是怎么做的。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多