Skip to content

Commit 84ae218

Browse files
Merge pull request #4 from microsoft/user/jeffand/prefix
Simplify batch create scenarios
2 parents 5811e0c + d008677 commit 84ae218

4 files changed

Lines changed: 300 additions & 73 deletions

File tree

examples/quickstart.py

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,12 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
5858
table_info = None
5959
created_this_run = False
6060

61-
# First check for existing table
62-
log_call("client.get_table_info('SampleItem')")
63-
existing = client.get_table_info("SampleItem")
64-
if existing:
65-
table_info = existing
61+
# Check for existing table using list_tables
62+
log_call("client.list_tables()")
63+
tables = client.list_tables()
64+
existing_table = next((t for t in tables if t.get("SchemaName") == "new_SampleItem"), None)
65+
if existing_table:
66+
table_info = client.get_table_info("new_SampleItem")
6667
created_this_run = False
6768
print({
6869
"table": table_info.get("entity_schema"),
@@ -71,13 +72,12 @@ def backoff_retry(op, *, delays=(0, 2, 5, 10, 20), retry_http_statuses=(400, 403
7172
"logical": table_info.get("entity_logical_name"),
7273
"metadata_id": table_info.get("metadata_id"),
7374
})
74-
7575
else:
7676
# Create it since it doesn't exist
7777
try:
7878
log_call("client.create_table('SampleItem', schema={code,count,amount,when,active})")
7979
table_info = client.create_table(
80-
"SampleItem",
80+
"new_SampleItem",
8181
{
8282
"code": "string",
8383
"count": "int",
@@ -139,12 +139,8 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None:
139139

140140
# 2) Create a record in the new table
141141
print("Create records (OData):")
142-
# Show planned creates before executing
143-
for _ in range(3):
144-
plan_call(f"client.create('{entity_set}', payload)")
145-
pause("Execute Create")
146-
record_ids: list[str] = []
147-
created_recs: list[dict] = []
142+
143+
# Prepare payloads
148144
create_payloads = [
149145
{
150146
f"{attr_prefix}_name": "Sample A",
@@ -172,14 +168,41 @@ def print_line_summaries(label: str, summaries: list[dict]) -> None:
172168
},
173169
]
174170

171+
# Show planned creates before executing
172+
plan_call(f"client.create('{entity_set}', single_payload)")
173+
plan_call(f"client.create('{entity_set}', [payload, ...])")
174+
pause("Execute Create")
175+
record_ids: list[str] = []
176+
created_recs: list[dict] = []
177+
175178
try:
176-
for payload in create_payloads:
177-
log_call(f"client.create('{entity_set}', payload)")
178-
rec = backoff_retry(lambda p=payload: client.create(entity_set, p))
179-
created_recs.append(rec)
180-
rid = rec.get(id_key)
181-
if rid:
182-
record_ids.append(rid)
179+
# Create the first record
180+
single_payload = create_payloads[0]
181+
log_call(f"client.create('{entity_set}', single_payload)")
182+
rec = backoff_retry(lambda: client.create(entity_set, single_payload))
183+
created_recs.append(rec)
184+
rid = rec.get(id_key)
185+
if rid:
186+
record_ids.append(rid)
187+
188+
# Create the remaining records in a single batch call
189+
batch_payloads = create_payloads[1:]
190+
if batch_payloads:
191+
log_call(f"client.create('{entity_set}', batch_payloads)")
192+
batch_recs = backoff_retry(lambda: client.create(entity_set, batch_payloads))
193+
# If the batch call returns a list, extend; else, append
194+
if isinstance(batch_recs, list):
195+
created_recs.extend(batch_recs)
196+
for rec in batch_recs:
197+
rid = rec.get(id_key)
198+
if rid:
199+
record_ids.append(rid)
200+
else:
201+
created_recs.append(batch_recs)
202+
rid = batch_recs.get(id_key)
203+
if rid:
204+
record_ids.append(rid)
205+
183206
print({"entity": logical, "created_ids": record_ids})
184207
# Summarize the created records from the returned payloads
185208
summaries = []
@@ -321,11 +344,11 @@ def _retry_if(ex: Exception) -> bool:
321344
print("Cleanup (Metadata):")
322345
try:
323346
# Delete if present, regardless of whether it was created in this run
324-
log_call("client.get_table_info('SampleItem')")
325-
info = client.get_table_info("SampleItem")
347+
log_call("client.get_table_info('new_SampleItem')")
348+
info = client.get_table_info("new_SampleItem")
326349
if info:
327-
log_call("client.delete_table('SampleItem')")
328-
client.delete_table("SampleItem")
350+
log_call("client.delete_table('new_SampleItem')")
351+
client.delete_table("new_SampleItem")
329352
print({"table_deleted": True})
330353
else:
331354
print({"table_deleted": False, "reason": "not found"})

src/dataverse_sdk/client.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any, Dict, Optional
3+
from typing import Any, Dict, Optional, List, Union
44

55
from azure.core.credentials import TokenCredential
66

@@ -63,25 +63,29 @@ def _get_odata(self) -> ODataClient:
6363
return self._odata
6464

6565
# CRUD
66-
def create(self, entity: str, record_data: dict) -> dict:
67-
"""Create a record and return its full representation.
66+
def create(self, entity: str, record_data: Union[Dict[str, Any], List[Dict[str, Any]], Any]) -> Union[Dict[str, Any], List[Dict[str, Any]]]:
67+
"""Create one or more records and return their full representation(s).
6868
6969
Parameters
7070
----------
7171
entity : str
7272
Entity set name (plural logical name), e.g., ``"accounts"``.
73-
record_data : dict
74-
Field-value pairs to set on the new record.
73+
record_data : dict, list of dict, or pandas.DataFrame
74+
Single record (dict), list of records, or pandas DataFrame with field-value pairs.
7575
7676
Returns
7777
-------
78-
dict
79-
The created record as returned by the Web API (``Prefer: return=representation``).
78+
dict or list of dict
79+
For single record: the created record as returned by the Web API.
80+
For multiple records: list of created records.
81+
Records are created using batch requests with a batch size of 25 for optimal performance.
8082
8183
Raises
8284
------
8385
requests.exceptions.HTTPError
8486
If the request fails (via ``raise_for_status`` in the underlying client).
87+
TypeError
88+
If record_data is not a supported type (dict, list, or pandas DataFrame).
8589
"""
8690
return self._get_odata().create(entity, record_data)
8791

@@ -196,6 +200,15 @@ def delete_table(self, tablename: str) -> None:
196200
"""
197201
self._get_odata().delete_table(tablename)
198202

203+
def list_tables(self) -> list[str]:
204+
"""List all custom tables in the Dataverse environment.
205+
206+
Returns
207+
-------
208+
list[str]
209+
A list of table names.
210+
"""
211+
return self._get_odata().list_tables()
199212

200213
__all__ = ["DataverseClient"]
201214

0 commit comments

Comments
 (0)