@@ -92,14 +92,25 @@ def _normalize_cache_key(table_schema_name: str) -> str:
9292
9393 @staticmethod
9494 def _lowercase_keys (record : Dict [str , Any ]) -> Dict [str , Any ]:
95- """Convert all dictionary keys to lowercase for case-insensitive column names.
95+ """Normalize dictionary keys to lowercase for case-insensitive column names.
9696
9797 Dataverse LogicalNames for attributes are stored lowercase, but users may
9898 provide PascalCase names (matching SchemaName). This normalizes the input.
99+ This function lowercases all string keys except OData annotation keys,
100+ which must remain case-sensitive.
99101 """
100102 if not isinstance (record , dict ):
101103 return record
102- return {k .lower () if isinstance (k , str ) else k : v for k , v in record .items ()}
104+
105+ new_record = {}
106+
107+ # Preserve OData annotation keys as they are case sensitive
108+ for k , v in record .items ():
109+ if isinstance (k , str ) and "@odata" in k :
110+ new_record [k ] = v
111+ else :
112+ new_record [k .lower () if isinstance (k , str ) else k ] = v
113+ return new_record
103114
104115 @staticmethod
105116 def _lowercase_list (items : Optional [List [str ]]) -> Optional [List [str ]]:
@@ -269,7 +280,7 @@ def _create(self, entity_set: str, table_schema_name: str, record: Dict[str, Any
269280 .. note::
270281 Relies on ``OData-EntityId`` (canonical) or ``Location`` response header. No response body parsing is performed. Raises ``RuntimeError`` if neither header contains a GUID.
271282 """
272- # Lowercase all keys to match Dataverse LogicalName expectations
283+ # Lowercase Dataverse attribute keys; keep OData annotation keys unchanged
273284 record = self ._lowercase_keys (record )
274285 record = self ._convert_labels_to_ints (table_schema_name , record )
275286 url = f"{ self .api } /{ entity_set } "
@@ -313,7 +324,7 @@ def _create_multiple(self, entity_set: str, table_schema_name: str, records: Lis
313324 logical_name = table_schema_name .lower ()
314325 enriched : List [Dict [str , Any ]] = []
315326 for r in records :
316- # Lowercase all keys to match Dataverse LogicalName expectations
327+ # Lowercase Dataverse attribute keys; keep OData annotation keys unchanged
317328 r = self ._lowercase_keys (r )
318329 r = self ._convert_labels_to_ints (table_schema_name , r )
319330 if "@odata.type" in r or not need_logical :
@@ -506,7 +517,7 @@ def _update(self, table_schema_name: str, key: str, data: Dict[str, Any]) -> Non
506517 :return: ``None``
507518 :rtype: ``None``
508519 """
509- # Lowercase all keys to match Dataverse LogicalName expectations
520+ # Lowercase Dataverse attribute keys; keep OData annotation keys unchanged
510521 data = self ._lowercase_keys (data )
511522 data = self ._convert_labels_to_ints (table_schema_name , data )
512523 entity_set = self ._entity_set_from_schema_name (table_schema_name )
@@ -540,7 +551,7 @@ def _update_multiple(self, entity_set: str, table_schema_name: str, records: Lis
540551 logical_name = table_schema_name .lower ()
541552 enriched : List [Dict [str , Any ]] = []
542553 for r in records :
543- # Lowercase all keys to match Dataverse LogicalName expectations
554+ # Lowercase Dataverse attribute keys; keep OData annotation keys unchanged
544555 r = self ._lowercase_keys (r )
545556 r = self ._convert_labels_to_ints (table_schema_name , r )
546557 if "@odata.type" in r or not need_logical :
0 commit comments