使用 OData 连接表

若要控制从相关表记录返回的数据,请使用包含导航属性的 $expand查询选项

  • 查询中最多可以包含 15 $expand 个选项。 每个 $expand 选项都会创建一个可能影响性能的联接。
  • 展开集合值导航属性的查询可能会返回那些不反映最近更改的属性的缓存数据。 建议在 If-None-Match 头中使用 null 的值来覆盖浏览器缓存。 了解如何使用 HTTP 标头 以获取更多信息。

下表介绍了可在某些选项中应用的$expand

选项 Description 详细信息
$select 选择返回的属性。 选择列
$filter 对于集合值导航属性,请限制返回的记录。 筛选行
$orderby 对于集合值导航属性,控制返回的记录的顺序。 不支持嵌套 $expand 嵌套的集合值导航属性$expand
$top 对于集合值导航属性,请限制返回的记录数。 不支持嵌套$expand 集合类型导航属性中的嵌套$expand
$expand 展开相关实体集中的导航属性。 在 $expand 中使用 $expand 形成称为嵌套 $expand 的结构。 单值导航属性的嵌套扩展集合值导航属性的嵌套扩展操作

这些选项是 OData 版本 4.0 第 1 部分:协议加 Errata 02 11.2.4.2.1 展开选项中所述的查询选项的子集。 Dataverse Web API 不支持选项 $skip$count$search$levels

将这些选项与 $expand 一起使用,并添加在导航属性名称后的括号中。 用分号分隔每个选项(;)。

例如,以下查询:

  • 请求account.name属性

  • 联接 AccountTasks 集合值导航属性请求:

    • task.subject 属性
    • task.subject其中包含字符串“Task
    • task.createdon 日期排序,降序
/accounts?$select=name&$expand=Account_Tasks($select=subject;$filter=contains(subject,'Task');$orderby=createdon desc)

利用 $select 对列进行限制

与任何查询一样,使用$select时,请始终限制返回的$expand列。 例如,以下请求在扩展结果中从contact.fullname实体类型返回contact.fullnametask.subject值:

请求:

GET [Organization URI]/api/data/v9.2/accounts?$select=name
&$expand=primarycontactid($select=fullname),Account_Tasks($select=subject)
Prefer: odata.maxpagesize=1
If-None-Match: null
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

响应:

HTTP/1.1 200 OK
OData-Version: 4.0
Preference-Applied: odata.maxpagesize=1

{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#accounts(name,primarycontactid(fullname),Account_Tasks(subject))",
    "value": [
        {
            "@odata.etag": "W/\"80649578\"",
            "name": "Litware, Inc. (sample)",
            "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
            "primarycontactid": {
                "fullname": "Susanna Stubberod (sample)",
                "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd"
            },
            "Account_Tasks": [
                {
                    "@odata.etag": "W/\"80649460\"",
                    "subject": "Task 1 for Litware",
                    "_regardingobjectid_value": "78914942-34cb-ed11-b596-0022481d68cd",
                    "activityid": "f68393c1-34cb-ed11-b597-000d3a993550"
                }
            ],
            "Account_Tasks@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts(78914942-34cb-ed11-b596-0022481d68cd)/Account_Tasks?$select=subject"
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts?$select=name&$expand=primarycontactid($select=fullname),Account_Tasks($select=subject)&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253caccountid%2520last%253d%2522%257b78914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520first%253d%2522%257b78914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

重要

请记住,有两种类型的导航属性。 详细了解 Web API 导航属性

  • 单值 导航属性对应于支持多对一关系的查找属性,并允许设置对另一条记录的引用。

  • 集合值 导航属性与一对多或多对多关系相对应。

扩展集合值导航属性可以使响应的大小以难以预测的方式很大。 必须包含限制来控制返回的数据量。 可以使用分页来限制记录数。 详细了解分页结果

对应用于集合值导航属性的嵌套$expand选项的分页方式有显著差异。 详细了解如何扩展集合值导航属性

展开单值导航属性

以下示例演示如何检索联系人记录,包括主要联系人和创建记录的用户。

请求:

GET [Organization URI]/api/data/v9.2/accounts?$select=name
&$expand=primarycontactid($select=contactid,fullname),createdby($select=fullname)  
Prefer: odata.maxpagesize=2
If-None-Match: null
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0

响应:

HTTP/1.1 200 OK  
Content-Type: application/json; odata.metadata=minimal
Preference-Applied: odata.maxpagesize=2
OData-Version: 4.0  
  
{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#accounts(name,primarycontactid(contactid,fullname),createdby(fullname))",
    "value": [
        {
            "@odata.etag": "W/\"80649578\"",
            "name": "Litware, Inc. (sample)",
            "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
            "primarycontactid": {
                "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd",
                "fullname": "Susanna Stubberod (sample)"
            },
            "createdby": {
                "fullname": "System Administrator",
                "systemuserid": "4026be43-6b69-e111-8f65-78e7d1620f5e",
                "ownerid": "4026be43-6b69-e111-8f65-78e7d1620f5e"
            }
        },
        {
            "@odata.etag": "W/\"80649580\"",
            "name": "Adventure Works (sample)",
            "accountid": "7a914942-34cb-ed11-b596-0022481d68cd",
            "primarycontactid": {
                "contactid": "72bf4d48-34cb-ed11-b596-0022481d68cd",
                "fullname": "Nancy Anderson (sample)"
            },
            "createdby": {
                "fullname": "System Administrator",
                "systemuserid": "4026be43-6b69-e111-8f65-78e7d1620f5e",
                "ownerid": "4026be43-6b69-e111-8f65-78e7d1620f5e"
            }
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts?$select=name%0A&$expand=primarycontactid($select=contactid,fullname),createdby($select=fullname)&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253caccountid%2520last%253d%2522%257b7A914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520first%253d%2522%257b78914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

createdby单值导航属性返回 systemuser EntityType 的实例。 systemuserid 属性和 ownerid 属性都会返回。 这是因为systemuser继承自主体 EntityType,并通过此继承与ownerid 共享主键。

但是, User (SystemUser) 表 具有 SystemUserId 的主键。 这两个属性systemuseridownerid具有相同的值。 详细了解 EntityType 继承

返回引用

可以通过使用 /$ref 选项扩展单值导航属性,返回相关记录的引用或链接,而不是直接返回数据。 以下示例返回具有每个主要联系人 URL 的属性的 JSON 对象 @odata.id

请求:

GET [Organization URI]/api/data/v9.2/accounts?$select=name
&$expand=primarycontactid/$ref  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

响应:

HTTP/1.1 200 OK  
Content-Type: application/json; odata.metadata=minimal
Preference-Applied: odata.maxpagesize=2
OData-Version: 4.0  
  
{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#accounts(name,primarycontactid,primarycontactid/$ref())",
    "value": [
        {
            "@odata.etag": "W/\"80649578\"",
            "name": "Litware, Inc. (sample)",
            "_primarycontactid_value": "70bf4d48-34cb-ed11-b596-0022481d68cd",
            "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
            "primarycontactid": {
                "@odata.id": "[Organization URI]/api/data/v9.2/contacts(70bf4d48-34cb-ed11-b596-0022481d68cd)"
            }
        },
        {
            "@odata.etag": "W/\"80649580\"",
            "name": "Adventure Works (sample)",
            "_primarycontactid_value": "72bf4d48-34cb-ed11-b596-0022481d68cd",
            "accountid": "7a914942-34cb-ed11-b596-0022481d68cd",
            "primarycontactid": {
                "@odata.id": "[Organization URI]/api/data/v9.2/contacts(72bf4d48-34cb-ed11-b596-0022481d68cd)"
            }
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts?$select=name%0A&$expand=primarycontactid/$ref&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253caccountid%2520last%253d%2522%257b7A914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520first%253d%2522%257b78914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

只能将 /$ref 选项用于单值导航属性。 如果将它与集合值导航属性一起使用,则会出现以下错误:

{
    "error": {
        "code": "0x80060888",
        "message": "Expand with $ref is only supported on lookup type navigation property."
    }
}

单值导航属性的嵌套扩展

通过将选项嵌套在另一$expand$expand个选项中,可以将单值导航属性扩展到多个级别。

以下查询返回 task 记录,并展开与其相关的 contact、与 contact 相关的 account,以及创建 account 记录的 systemuser

请求:

GET [Organization URI]/api/data/v9.2/tasks?$select=subject
&$expand=regardingobjectid_contact_task($select=fullname;
 $expand=parentcustomerid_account($select=name;
  $expand=createdby($select=fullname)))  
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  
Prefer: odata.maxpagesize=2

响应:

HTTP/1.1 200 OK  
Content-Type: application/json; odata.metadata=minimal
Preference-Applied: odata.maxpagesize=2
OData-Version: 4.0 

{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#tasks(subject,regardingobjectid_contact_task(fullname,parentcustomerid_account(name,createdby(fullname))))",
    "value": [
        {
            "@odata.etag": "W/\"80730855\"",
            "subject": "Task 1 for Susanna Stubberod",
            "activityid": "e9a8c72c-dbcc-ed11-b597-000d3a993550",
            "regardingobjectid_contact_task": {
                "fullname": "Susanna Stubberod (sample)",
                "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd",
                "parentcustomerid_account": {
                    "name": "Litware, Inc. (sample)",
                    "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
                    "createdby": {
                        "fullname": "System Administrator",
                        "systemuserid": "4026be43-6b69-e111-8f65-78e7d1620f5e",
                        "ownerid": "4026be43-6b69-e111-8f65-78e7d1620f5e"
                    }
                }
            }
        },
        {
            "@odata.etag": "W/\"80730861\"",
            "subject": "Task 2 for Susanna Stubberod",
            "activityid": "c206f534-dbcc-ed11-b597-000d3a993550",
            "regardingobjectid_contact_task": {
                "fullname": "Susanna Stubberod (sample)",
                "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd",
                "parentcustomerid_account": {
                    "name": "Litware, Inc. (sample)",
                    "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
                    "createdby": {
                        "fullname": "System Administrator",
                        "systemuserid": "4026be43-6b69-e111-8f65-78e7d1620f5e",
                        "ownerid": "4026be43-6b69-e111-8f65-78e7d1620f5e"
                    }
                }
            }
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/tasks?$select=subject&$expand=regardingobjectid_contact_task($select=fullname;$expand=parentcustomerid_account($select=name;$expand=createdby($select=fullname)))&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253cactivityid%2520last%253d%2522%257bC206F534-DBCC-ED11-B597-000D3A993550%257d%2522%2520first%253d%2522%257bE9A8C72C-DBCC-ED11-B597-000D3A993550%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

展开集合值导航属性

响应中存在一些重要差异,具体取决于是否在查询中的任何位置使用嵌套 $expand 的集合值导航属性。

嵌套$expand 单个$expand
分页 对展开的行进行分页。 仅对 EntitySet 资源进行分页。 <property name>@odata.nextLink 扩展行的 URL 不包括分页信息。
$top$orderby 受支持 是的
支持 N:N 关系 否。 请参阅 包含 N:N 关系的嵌套$expand 是的

集合值导航属性中使用的单个 $expand

如果仅使用单级 $expand,则不会对展开的行应用分页。 如果包含 Prefer: odata.maxpagesize 请求标头,则分页仅应用于查询的 EntitySet 资源。

每个扩展的集合值导航属性返回一个 <property>@odata.nextLink 不包含分页信息的 URL。 这是一个 URL,表示附加了查询选项的关系的筛选集合。 可以使用该 URL 发送单独的 GET 请求,并返回原始请求中返回的相同行。 可以将分页应用于该请求。

由于没有对已扩展的记录应用分页,因此每个扩展后的集合值导航属性最多可以返回 5,000 条相关表记录。 根据你的数据和查询,可能涉及大量数据。 返回大量数据可能会影响性能,并可能导致请求超时。请谨慎对待你撰写的查询。 可以使用$top$filter$orderby选项来控制返回的记录总数。

以下示例在检索帐户记录时包含单次扩展Account_Taskscontact_customer_accounts。 请求 Prefer: odata.maxpagesize=1 标头可确保在第一页中只返回一个帐户记录。

请求:

GET [Organization URI]/api/data/v9.2/accounts?$select=name,accountid
&$expand=Account_Tasks($select=subject),contact_customer_accounts($select=fullname)
Prefer: odata.maxpagesize=1
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

响应:

HTTP/1.1 200 OK  
Content-Type: application/json; odata.metadata=minimal
Preference-Applied: odata.maxpagesize=1
OData-Version: 4.0 

{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#accounts(name,accountid,Account_Tasks(subject),contact_customer_accounts(fullname))",
    "value": [
        {
            "@odata.etag": "W/\"80649578\"",
            "name": "Litware, Inc. (sample)",
            "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
            "Account_Tasks": [
                {
                    "@odata.etag": "W/\"80730894\"",
                    "subject": "Task 1 for Litware",
                    "_regardingobjectid_value": "78914942-34cb-ed11-b596-0022481d68cd",
                    "activityid": "be9f6557-e2cc-ed11-b597-000d3a993550"
                },
                {
                    "@odata.etag": "W/\"80730903\"",
                    "subject": "Task 2 for Litware",
                    "_regardingobjectid_value": "78914942-34cb-ed11-b596-0022481d68cd",
                    "activityid": "605dbd65-e2cc-ed11-b597-000d3a993550"
                },
                {
                    "@odata.etag": "W/\"80730909\"",
                    "subject": "Task 3 for Litware",
                    "_regardingobjectid_value": "78914942-34cb-ed11-b596-0022481d68cd",
                    "activityid": "a718856c-e2cc-ed11-b597-000d3a993550"
                }
            ],
            "Account_Tasks@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts(78914942-34cb-ed11-b596-0022481d68cd)/Account_Tasks?$select=subject",
            "contact_customer_accounts": [
                {
                    "@odata.etag": "W/\"80648695\"",
                    "fullname": "Susanna Stubberod (sample)",
                    "_parentcustomerid_value": "78914942-34cb-ed11-b596-0022481d68cd",
                    "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd"
                }
            ],
            "contact_customer_accounts@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts(78914942-34cb-ed11-b596-0022481d68cd)/contact_customer_accounts?$select=fullname"
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts?$select=name,accountid&$expand=Account_Tasks($select=subject),contact_customer_accounts($select=fullname)&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253caccountid%2520last%253d%2522%257b7A914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520first%253d%2522%257b78914942-34CB-ED11-B596-0022481D68CD%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

将此响应与以下包含嵌套 $expand 的示例进行比较。 请水平滚动示例响应,以查看只有 @odata.nextLink 帐户结果的 URL 包含分页信息。

集合值导航属性中的嵌套$expand

如果在查询的任何位置使用嵌套的$expand,并且包含Prefer: odata.maxpagesize请求标头,则分页将应用于每个已展开的集合。

每个扩展的集合值导航属性返回一个包含分页信息的 <property>@odata.nextLink URL。 可以使用该 URL 发送单独的 GET 请求,它将返回原始请求中未包含的下一组记录。

不能使用 $top$orderby 选项来限制使用嵌套 $expand返回的记录总数。 如果使用以下选项,将返回以下错误:

{
    "error": {
        "code": "0x80060888",
        "message": "Only $select and $filter clause can be provided while doing $expand on many-to-one relationship or nested one-to-many relationship."
    }
}

以下示例基于上一个示例并使用相同的数据。 唯一的区别是,在单值导航属性的 URL 中添加这个嵌套$expand,用于返回联系人的拥有用户:;$expand=owninguser($select=fullname)

请求:

GET [Organization URI]/api/data/v9.2/accounts?$select=name,accountid
&$expand=Account_Tasks($select=subject),contact_customer_accounts($select=fullname;
$expand=owninguser($select=fullname))
Prefer: odata.maxpagesize=1
Accept: application/json  
OData-MaxVersion: 4.0  
OData-Version: 4.0  

响应:

HTTP/1.1 200 OK  
Content-Type: application/json; odata.metadata=minimal
Preference-Applied: odata.maxpagesize=1
OData-Version: 4.0 

{
    "@odata.context": "[Organization URI]/api/data/v9.2/$metadata#accounts(name,accountid,Account_Tasks(subject),contact_customer_accounts(fullname,owninguser(fullname)))",
    "value": [
        {
            "@odata.etag": "W/\"80649578\"",
            "name": "Litware, Inc. (sample)",
            "accountid": "78914942-34cb-ed11-b596-0022481d68cd",
            "Account_Tasks": [
                {
                    "subject": "Task 1 for Litware",
                    "activityid": "be9f6557-e2cc-ed11-b597-000d3a993550"
                }
            ],
            "Account_Tasks@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts(78914942-34cb-ed11-b596-0022481d68cd)/Account_Tasks?$select=subject,description&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%2520countOfRecords%253d%25221%2522%253e%253cactivityid%2520last%253d%2522%257bbe9f6557-e2cc-ed11-b597-000d3a993550%257d%2522%2520first%253d%2522%257bbe9f6557-e2cc-ed11-b597-000d3a993550%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E",
            "contact_customer_accounts": [
                {
                    "fullname": "Susanna Stubberod (sample)",
                    "contactid": "70bf4d48-34cb-ed11-b596-0022481d68cd",
                    "owninguser": {
                        "fullname": "System Administrator",
                        "systemuserid": "4026be43-6b69-e111-8f65-78e7d1620f5e",
                        "ownerid": "4026be43-6b69-e111-8f65-78e7d1620f5e"
                    }
                }
            ],
            "contact_customer_accounts@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts(78914942-34cb-ed11-b596-0022481d68cd)/contact_customer_accounts?$select=fullname&$expand=owninguser($select=fullname)&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%2520countOfRecords%253d%25221%2522%253e%253ccontactid%2520last%253d%2522%257b70bf4d48-34cb-ed11-b596-0022481d68cd%257d%2522%2520first%253d%2522%257b70bf4d48-34cb-ed11-b596-0022481d68cd%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
        }
    ],
    "@odata.nextLink": "[Organization URI]/api/data/v9.2/accounts?$select=name,accountid&$expand=Account_Tasks($select=subject,description),contact_customer_accounts($select=fullname;$expand=owninguser($select=fullname))&$skiptoken=%3Ccookie%20pagenumber=%222%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%2520countOfRecords%253d%25221%2522%253e%253caccountid%2520last%253d%2522%257b78914942-34cb-ed11-b596-0022481d68cd%257d%2522%2520first%253d%2522%257b78914942-34cb-ed11-b596-0022481d68cd%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E"
}

将此响应与前面的示例进行比较,该示例不使用嵌套 $expand。 在此响应中:

  • 请求Prefer: odata.maxpagesize=1标头应用于返回的taskAccount_Tasks记录。
  • 只返回一个任务,而不是返回三个任务。
  • URL Account_Tasks@odata.nextLink 返回接下来的两个任务。
  • 请水平滚动示例响应,以查看 Account_Tasks@odata.nextLinkcontact_customer_accounts@odata.nextLink@odata.nextLink URL 中包含的分页信息。

嵌套 $expand 与 N:N 关系

当集合值导航属性表示 N:N 关系时,使用嵌套 $expand 语句时会收到以下错误:

{
   "error": {
      "code": "0x80060888",
      "message": "The navigation property '<NAME>' cannot be expanded. Only many-to-one relationships are supported for nested expansion."
   }
}

例如,使用 Dynamics Lead 表(与 联系人表contactleads_association N:N 关系),以下查询返回错误,因为它包含;$expand=createdby

GET [Organization URI]/contacts?$select=fullname$expand=contactleads_association($select=fullname;$expand=createdby)

若要避免此错误,可以使用 FetchXml 构造查询。 例如:

<fetch>
  <entity name='contact'>
    <attribute name='fullname' />
    <link-entity name='contactleads' 
      from='contactid' 
      to='contactid' 
      alias='cl'>
      <link-entity name='lead' 
         from='leadid' 
         to='leadid' 
         alias='lead'>
        <attribute name='fullname' />
        <link-entity name='systemuser' 
           from='systemuserid' 
           to='createdby' 
           alias='systemuser'>
          <attribute name='fullname' />
        </link-entity>
      </link-entity>
    </link-entity>
  </entity>
</fetch>

详细了解如何通过 FetchXml 使用多对多关系联接表

后续步骤

了解如何对行进行排序。