[この記事はプレリリース ドキュメントであり、変更されることがあります。]
この記事では、SDK を使用して Dataverse のデータとメタデータを操作するコード例をいくつか示します。 この記事に進む前に、まず「 はじめに (プレビュー)」 を読んでください。
基本操作
アカウント テーブルで動作するコード例を次に示します。
from azure.identity import InteractiveBrowserCredential
from PowerPlatform.Dataverse.client import DataverseClient
base_url = "https://<myorg>.crm.dynamics.com"
client = DataverseClient(base_url=base_url, credential=InteractiveBrowserCredential())
# Create an account and set some properties (returns list[str] of new GUIDs)
account_id = client.create("account", {"name": "Acme, Inc.", "telephone1": "555-0100"})[0]
# Read an account
account = client.get("account", account_id)
# Update an account (returns None)
client.update("account", account_id, {"telephone1": "555-0199"})
# Delete an account
client.delete("account", account_id)
一括操作
ここでは、一括更新を実行する例をいくつか示します。
# Bulk update (broadcast) – apply same patch to several IDs
ids = client.create("account", [
{"name": "Contoso"},
{"name": "Fabrikam"},
])
client.update("account", ids, {"telephone1": "555-0200"}) # broadcast patch
# Bulk update (1:1) – list of patches matches list of IDs
client.update("account", ids, [
{"telephone1": "555-1200"},
{"telephone1": "555-1300"},
])
print({"multi_update": "ok"})
ここでは、複数のアカウントを作成する例を示します。
create(logical_name, payloads)にペイロードの一覧を渡して、コレクション バインドMicrosoft.Dynamics.CRM.CreateMultipleアクションを呼び出します。 このメソッドは、作成されたレコード ID の list[str] を返します。
# Bulk create accounts (returns list of GUIDs)
payloads = [
{"name": "Contoso"},
{"name": "Fabrikam"},
{"name": "Northwind"},
]
ids = client.create("account", payloads)
assert isinstance(ids, list) and all(isinstance(x, str) for x in ids)
print({"created_ids": ids})
一括操作に関する追加情報:
- セマンティクスの一貫性を保つために
None(単一の更新と同じ) を返します。 - ブロードキャストとレコードごとの比較は、
changesパラメーターがディクショナリかリストかによって決まります。 - UpdateMultiple アクション ターゲットを構築すると、主キー属性が自動的に挿入されます。
- ペイロードが @odata.typeを省略すると、自動的にスタンプされます (キャッシュされた論理名参照)。
- 応答には ID のみが含まれます。SDK はそれらの GUID 文字列を返します。
- 単一レコード作成では、GUID の 1 要素リストが返されます。
-
@odata.typeのメタデータ検索は、エンティティ セット (メモリ内キャッシュ) ごとに 1 回実行されます。
ファイルのアップロード
アカウント レコードの "sample_filecolumn" という名前のファイル列に 'test.pdf' という名前の ファイル をアップロードする例をいくつか次に示します。 1 つ目の例は 128 MB 未満のファイル サイズに対し、2 番目の例は 128 MB を超えるファイル サイズです。
client.upload_file('account', record_id, 'sample_filecolumn', 'test.pdf')
client.upload_file('account', record_id, 'sample_filecolumn', 'test.pdf', mode='chunk', if_none_match=True)
ファイルのアップロードに関する追加情報:
-
upload_fileは、ファイル サイズに基づいて使用する 3 つの方法のいずれかを選択します。 ファイル サイズが 128 MB 未満の場合、SDK はupload_file_smallを使用します。それ以外の場合、SDK はupload_file_chunk -
upload_file_smallは 1 つの Web API 呼び出しを行い、128 MB < ファイル サイズのみをサポートします。 -
upload_file_chunkPATCH と Content-Range を使用してファイルをアップロードします (Dataverse メッセージと比較して HTTP 標準に合わせて調整されます)。 1 という 2 つのステージで構成されます。 実際のアップロードに使用されるヘッダーを取得するための PATCH 要求、および 2。 実際のアップロード (チャンク単位)。 この関数は、最初のステージで返される ODatax-ms-chunk-sizeを使用してチャンク サイズ (通常は 4 MB) を決定し、アップロードのメタデータとしてContent-RangeとContent-Lengthを使用します。 Web API 呼び出しの合計数は、チャンク数 + 1 です。
ページングで複数の項目を取得する
get関数を使用して、結果をページごとにストリーミングします。 合計結果を $top に上限を設定し、 page_size パラメーターを使用してページごとのサイズをヒントすることができます。 SDK は内部的に OData prefer ヘッダー odata.maxpagesizeを設定します。
pages = client.get(
"account",
select=["accountid", "name", "createdon"],
orderby=["name asc"],
top=10, # stop after 10 total rows (optional)
page_size=3, # ask for ~3 per page (optional)
)
total = 0
for page in pages: # each page is a list[dict]
print({"page_size": len(page), "sample": page[:2]})
total += len(page)
print({"total_rows": total})
サポートされているパラメーターの一覧を次に示します。ただし、 logical_name以外はすべて省略可能です。
- logical_name: str — 論理 (単数形) 名 (例: "account")。
- select: list[str] |なし — 列 -> $select (コンマで結合)。
- filter: str | None — OData $filter expression (for example, contains(name,'Acme') and statecode eq 0).
- orderby: list[str] |None — 式の並べ替え -> $orderby (コンマ結合)。
- top: int |なし — $top経由のグローバル上限 (最初の要求に適用され、サービスはページ間で適用されます)。
- expand: list[str] | None — ナビゲーション拡張 -> $expand; 生の句を渡します (例: primarycontactid($select=fullname,emailaddress1))。
- page_size: int |None — Prefer: odata.maxpagesize=<N> を使用したページ単位のヒント (保証されていません。最後のページが小さい場合があります)。
戻り値とセマンティクスの一覧を次に示します。
-
$select、$filter、$orderby、$expand、$top、最初の要求の対応する OData クエリ オプションに直接マップされます。 -
$top行の合計数を制限します。サービスはこれらの行を複数のページに分割することがあります。 - page_size (
Prefer: odata.maxpagesize) はヒントであり、サーバーは実際のページ境界を決定します。 - 空でないページ (list[dict]) を生成するジェネレーターを返します。 空のページはスキップされます。
- 生成された各リストは、Web API の値ページに対応します。
-
@odata.nextLinkが残っていない場合、またはサーバー側で
$topが満たされた場合、イテレーションが停止します。 - ジェネレーターはすべての結果を具体化するわけではありません。ページは遅延して取得されます。
サポートされているすべてのパラメーターと予想される応答を含む例を見てみましょう。
pages = client.get(
"account",
select=["accountid", "name", "createdon", "primarycontactid"],
filter="contains(name,'Acme') and statecode eq 0",
orderby=["name asc", "createdon desc"],
top=5,
expand=["primarycontactid($select=fullname,emailaddress1)"],
page_size=2,
)
for page in pages: # page is list[dict]
# Expected page shape (illustrative)
# [
# {
# "accountid": "00000000-0000-0000-0000-000000000001"
# "name": "Acme West"
# "createdon": "2025-08-01T12:34:56Z"
# "primarycontactid": {
# "contactid": "00000000-0000-0000-0000-0000000000aa"
# "fullname": "Jane Doe"
# "emailaddress1": "<jane@acme.com>"
# }
# "@odata.etag": "W/\"123456\""
# }
#
# ]
print({"page_size": len(page)})
テーブル メタデータ
カスタム テーブルを操作するためのコード例を見てみましょう。
# Support enumerations with labels in different languages
class Status(IntEnum):
Active = 1
Inactive = 2
Archived = 5
__labels__ = {
1033: {
"Active": "Active",
"Inactive": "Inactive",
"Archived": "Archived",
},
1036: {
"Active": "Actif",
"Inactive": "Inactif",
"Archived": "Archivé",
}
}
# Create a simple custom table and a few columns
info = client.create_table(
"SampleItem", # friendly name; defaults to SchemaName new_SampleItem
{
"code": "string",
"count": "int",
"amount": "decimal",
"when": "datetime",
"active": "bool",
"status": Status,
},
)
logical = info["entity_logical_name"] # for example, "new_sampleitem"
# Create a record in the new table
# Set your publisher prefix (used when creating the table). If you used the default, it's "new".
prefix = "new"
name_attr = f"{prefix}_name"
id_attr = f"{logical}id"
rec_id = client.create(logical, {name_attr: "Sample A"})[0]
# Clean up
client.delete(logical, rec_id) # delete record
client.delete_table("SampleItem") # delete table (friendly name or explicit schema new_SampleItem)
カスタム テーブル メタデータの操作に関する追加情報:
-
createは常に GUID のリストを返します (単一入力の場合は length=1)。 -
updateとdeleteは、1 つのインターフェイスと複数のインターフェイスの両方のNoneを返します。 - ペイロードの一覧を
createに渡すと、一括作成がトリガーされ、ID の list[str] が返されます。 -
getでは、レコード ID を使用した単一レコードの取得または結果セットのページングがサポートされています (列を制限する選択を優先します)。 - レコード ID を受け取る CRUD メソッドの場合は、GUID 文字列 (ハイフネーション 36 文字) を渡します。 GUID を括弧で囲むことは受け入れられますが、必須ではありません。
- SQL クエリは、
?sql=パラメーターを使用してエンティティ セット エンドポイントに対して直接実行されます。 サポートされるサブセットのみ (単一の SELECT、省略可能な WHERE/TOP/ORDER BY、エイリアス)。 サポートされていないコンストラクトは、サービスによって拒否されます。
SDK での pandas の使用
PandasODataClient は、低レベルのクライアントを囲むシン ラッパーです。 すべてのメソッドは、エンティティ セット (複数形) 名ではなく、論理 (単数形) 名 (アカウント、new_sampleitemなど) を受け入れます。
ワークフローについては、'quickstart_pandas.py' という名前の SDK ソース リポジトリのDataFrameを参照してください。