Title: Feature Request: Support OData Deep Inserts in create() and upsert() · Issue #149 · microsoft/PowerPlatform-DataverseClient-Python · GitHub
Open Graph Title: Feature Request: Support OData Deep Inserts in create() and upsert() · Issue #149 · microsoft/PowerPlatform-DataverseClient-Python
X Title: Feature Request: Support OData Deep Inserts in create() and upsert() · Issue #149 · microsoft/PowerPlatform-DataverseClient-Python
Description: Summary Add support for OData deep inserts in client.records.create() and client.records.upsert(), allowing parent and related child records to be created/upserted in a single API call. Motivation When importing data that involves a pare...
Open Graph Description: Summary Add support for OData deep inserts in client.records.create() and client.records.upsert(), allowing parent and related child records to be created/upserted in a single API call. Motivation ...
X Description: Summary Add support for OData deep inserts in client.records.create() and client.records.upsert(), allowing parent and related child records to be created/upserted in a single API call. Motivation ...
Opengraph URL: https://github.com/microsoft/PowerPlatform-DataverseClient-Python/issues/149
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Feature Request: Support OData Deep Inserts in create() and upsert()","articleBody":"## Summary\n\nAdd support for [OData deep inserts](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/create-entity-web-api#create-related-table-rows-in-one-operation) in `client.records.create()` and `client.records.upsert()`, allowing parent and related child records to be created/upserted in a single API call.\n\n## Motivation\n\nWhen importing data that involves a parent record and its related child records (e.g. via one-to-many relationships), the current SDK requires separate API calls for each table — first creating the parent, then creating each child record individually with a foreign key reference back to the parent. This is both verbose and inefficient, especially for bulk import scenarios.\n\nThe Dataverse Web API already natively supports deep inserts, where related records can be nested inside the parent payload using navigation property names. For example:\n\n```json\n{\n \"name\": \"Sample Account\",\n \"primarycontactid\": {\n \"firstname\": \"John\",\n \"lastname\": \"Smith\"\n },\n \"contact_customer_accounts\": [\n { \"firstname\": \"Jane\", \"lastname\": \"Doe\" },\n { \"firstname\": \"Bob\", \"lastname\": \"Jones\" }\n ]\n}\n```\n\nThe SDK does not currently surface this capability. Attempting to pass nested dicts/lists in the record payload will not work correctly because `_create()` lowercases all keys via `_lowercase_keys()`, which breaks case-sensitive navigation property names.\n\n## Proposed Behavior\n\nAllow `create()` and `upsert()` to accept nested dicts (for single-valued navigation properties) and lists of dicts (for collection-valued navigation properties) within the record payload. Navigation property keys should be preserved as-is (case-sensitive) and not lowercased.\n\n**Example usage:**\n\n```python\n# Deep insert: create parent + children in one call\nclient.records.create(\"account\", {\n \"name\": \"Contoso Ltd\",\n \"primarycontactid\": {\n \"firstname\": \"John\",\n \"lastname\": \"Smith\"\n },\n \"contact_customer_accounts\": [\n {\"firstname\": \"Jane\", \"lastname\": \"Doe\"},\n {\"firstname\": \"Bob\", \"lastname\": \"Jones\"},\n ]\n})\n```\n\n## Current Workaround\n\nCreate parent and child records in separate calls, manually managing the foreign key references:\n\n```python\nparent_id = client.records.create(\"account\", {\"name\": \"Contoso Ltd\"})\n\nclient.records.create(\"contact\", {\n \"firstname\": \"Jane\",\n \"lastname\": \"Doe\",\n \"parentcustomerid_account@odata.bind\": f\"/accounts({parent_id})\"\n})\n```\n\n## Additional Context\n\n- The Dataverse Web API documentation confirms deep insert support for both `POST` (create) and `PATCH` (upsert) operations.\n- The `_lowercase_keys()` call in `_create()` would need to distinguish between column names (which should be lowercased) and navigation property names (which are case-sensitive and should be preserved).\n- `CreateMultiple` / `UpsertMultiple` bulk operations may also benefit from this, depending on API support for deep inserts in batch payloads.\n","author":{"url":"https://github.com/JDziurlaj","@type":"Person","name":"JDziurlaj"},"datePublished":"2026-03-17T17:55:33.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/149/PowerPlatform-DataverseClient-Python/issues/149"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:52bd597a-b1a7-e8f7-3506-f66ca0daa01c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D5BC:2A5CAA:25AE67F:366AB8C:6A4D1C04 |
| html-safe-nonce | 28dec0bff7ec04b6b6aa488b4c78c5a17a94e008259359b5942ba2060b262af4 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENUJDOjJBNUNBQToyNUFFNjdGOjM2NkFCOEM6NkE0RDFDMDQiLCJ2aXNpdG9yX2lkIjoiMjQzMjMyMDExMjcxMzA3OTgxMiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 076b565313c4c2fd72123c199ef8e59927121d53772aaabfe8e7a702c46090de |
| hovercard-subject-tag | issue:4090199453 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/microsoft/PowerPlatform-DataverseClient-Python/149/issue_layout |
| twitter:image | https://opengraph.githubassets.com/f6642e811d09dfed03530ee6c483a8c92c39a925f4009cf6cc73e39fd7e2f0e0/microsoft/PowerPlatform-DataverseClient-Python/issues/149 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/f6642e811d09dfed03530ee6c483a8c92c39a925f4009cf6cc73e39fd7e2f0e0/microsoft/PowerPlatform-DataverseClient-Python/issues/149 |
| og:image:alt | Summary Add support for OData deep inserts in client.records.create() and client.records.upsert(), allowing parent and related child records to be created/upserted in a single API call. Motivation ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | JDziurlaj |
| hostname | github.com |
| expected-hostname | github.com |
| None | bcb4661e6fb4fe8b394c51ea02ccdb2236d40dc59afc75a3bbba50bf6517134c |
| turbo-cache-control | no-preview |
| go-import | github.com/microsoft/PowerPlatform-DataverseClient-Python git https://github.com/microsoft/PowerPlatform-DataverseClient-Python.git |
| octolytics-dimension-user_id | 6154722 |
| octolytics-dimension-user_login | microsoft |
| octolytics-dimension-repository_id | 1042273116 |
| octolytics-dimension-repository_nwo | microsoft/PowerPlatform-DataverseClient-Python |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1042273116 |
| octolytics-dimension-repository_network_root_nwo | microsoft/PowerPlatform-DataverseClient-Python |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | fb70bd3c4b2bec429781b65419e912c66e2d5581 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width