microsoft / microsoft/PowerPlatform-DataverseClient-Python

Typed column metadata reads via RetrieveMetadataChanges (one request, no @odata.type cast round-trip)

Open
#203 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
60
Forks
23
Avg merge
13h 53m
Merged PRs (30d)
3

Description

Summary

Reading type-specific column properties over /EntityDefinitions is a two-step dance: first read the generic attribute to get AttributeType/@odata.type, then re-issue a second GET with a derived-type URL cast (/Attributes/Microsoft.Dynamics.CRM.StringAttributeMetadata) to project the typed fields. The SDK does exactly this today (e.g. _bulk_fetch_picklists, extra_select="@odata.type,AttributeType").

Context: what the .NET modern client gives for free

ServiceClient gets fully-typed, polymorphic AttributeMetadata derived objects back in one RetrieveEntity/RetrieveAllEntities call and the caller just downcasts (attr is StringAttributeMetadata s). No second request, no discriminator juggling.

Proposed change

Add a typed read path backed by the Web API RetrieveMetadataChanges function -- the closest Web-API analog to the .NET single-request typed retrieve. It returns derived typed attributes in one call and supports property projection (via the query's AttributeQuery.Properties), so callers get small, typed payloads without the cast round-trip.

cols = client.tables.list_columns("account", typed=True)   # typed values, one request
col  = client.tables.get_column("account", "emailaddress1", typed=True)

Why this does not need a platform change

Payload size is controlled by the query's property projection, so the platform "omit null fields" ask is not a blocker -- we simply project only the properties we need. (Note: the .NET client itself uses plain Retrieve* + a client cache rather than RetrieveMetadataChanges; for a Web-API client wanting small typed payloads, RetrieveMetadataChanges with projection is the better fit. Design discussion welcome.)

Touchpoints

  • data/_odata.py -- new _retrieve_metadata_changes(...) issuing GET RetrieveMetadataChanges(Query=@p1)?@p1={...} with an EntityQueryExpression + AttributeQuery.Properties projection.
  • operations/tables.py + async twin -- typed=True on list_columns / get_column (keep the existing cast path as fallback).
  • Unit tests: request shape (projection, criteria) + typed mapping.
  • README + CHANGELOG.

Acceptance

  • list_columns(typed=True) returns typed values (e.g. MaxLength on string/memo, MinValue/MaxValue on int) in a single request, no @odata.type URL cast.
  • Property projection limits the payload to requested properties.

Related

  • #194 -- create-time column constraints (in progress).
  • microsoft/Dataverse-skills#119 -- documents the current two-step typed-read workaround.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in data/_odata.py and inspect the existing metadata cast path, then trace list_columns and get_column in operations/tables.py and their async twin. Add unit coverage for the RetrieveMetadataChanges request shape, projection, criteria, and typed mapping, plus update README and CHANGELOG. Done means typed reads return properties such as MaxLength or MinValue/MaxValue in one request, with the existing cast path retained as fallback.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.