Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird Beispielcode veranschaulicht, mit dem das SDK zum Arbeiten mit Dataverse-Daten und -Metadaten verwendet wird. Bevor Sie fortfahren, lesen Sie unbedingt "Erste Schritte".
Grundlegende Vorgänge
Hier ist Beispielcode, der auf der Kontotabelle ausgeführt wird.
from azure.identity import InteractiveBrowserCredential
from PowerPlatform.Dataverse.client import DataverseClient
# Replace <myorg> with the name of a valid environment.
base_url = "https://<myorg>.crm.dynamics.com"
client = DataverseClient(base_url=base_url, credential=InteractiveBrowserCredential())
# Create a record
account_id = client.records.create("account", {"name": "Contoso Ltd"})
# Read a record
account = client.records.retrieve("account", account_id)
print(account["name"])
# Read with expand fetches a related record in the same HTTP request
account = client.records.retrieve(
"account", account_id,
select=["name"],
expand=["primarycontactid"],
)
contact = (account.get("primarycontactid") or {})
print(contact.get("fullname"))
# Update a record
client.records.update("account", account_id, {"telephone1": "555-0199"})
# Delete a record
client.records.delete("account", account_id)
Kontext-Manager
Der Kontext-Manager verarbeitet automatische Bereinigung und HTTP-Verbindungspooling. Verwenden Sie die folgende Syntax, um den Kontext-Manager zu nutzen.
with DataverseClient("https://<myorg>.crm.dynamics.com", credential) as client:
Der folgende Arbeitscode veranschaulicht die Verwendung des Kontext-Managers.
from azure.identity import InteractiveBrowserCredential
from PowerPlatform.Dataverse.client import DataverseClient
# Connect to Dataverse
credential = InteractiveBrowserCredential()
with DataverseClient("https://<myorg>.crm.dynamics.com", credential) as client:
# Create a contact
contact_id = client.records.create("contact", {"firstname": "John", "lastname": "Doe"})
# Read the contact back
contact = client.records.retrieve("contact", contact_id, select=["firstname", "lastname"])
print(f"Created: {contact['firstname']} {contact['lastname']}")
# Clean up
client.records.delete("contact", contact_id)
# Session closed, caches cleared automatically
Massenvorgänge
Im Folgenden sind einige Beispiele aufgeführt, die Massenvorgänge ausführen.
# Bulk create
payloads = [
{"name": "Company A"},
{"name": "Company B"},
{"name": "Company C"}
]
ids = client.records.create("account", payloads)
# Bulk update (broadcast same change to all)
client.records.update("account", ids, {"industry": "Technology"})
# Bulk delete
client.records.delete("account", ids, use_bulk_delete=True)
Im folgenden Beispiel werden mehrere Konten erstellt. Übergeben Sie eine Nutzlastliste an create(logical_name, payloads), um die sammlungsgebundene Aktion Microsoft.Dynamics.CRM.CreateMultiple aufzurufen. Die Methode gibt erstellte Datensatz-IDs zurück list[str] .
# Bulk create accounts (returns list of GUIDs)
payloads = [
{"name": "Contoso"},
{"name": "Fabrikam"},
{"name": "Northwind"},
]
ids = client.records.create("account", payloads)
assert isinstance(ids, list) and all(isinstance(x, str) for x in ids)
print({"created_ids": ids})
Weitere Informationen zu Massenvorgängen:
- Gibt
None(identisch mit einzelnem Update) zurück, um die Semantik konsistent zu halten. - Ob es sich um Broadcast oder pro Datensatz handelt, hängt davon ab, ob der Parameter
changesein Wörterbuch oder eine Liste ist. - Das Primärschlüsselattribut wird beim Erstellen von UpdateMultiple-Aktionszielen automatisch eingefügt.
- Wenn eine Nutzlast @odata.type auslässt, fügt das SDK diese automatisch ein (Suche nach logischen Namen im Cache).
- Die Antwort enthält nur IDs – das SDK gibt diese GUID-Zeichenfolgen zurück.
- Die Erstellung eines einzelnen Datensatzes gibt eine Ein-Element-Liste von GUIDs zurück.
- Die Metadatensuche für
@odata.typewird einmal für jeden Entitätssatz (im Arbeitsspeicher zwischengespeichert) durchgeführt.
Upsert (Erstellen und Aktualisieren)
Eine allgemeine Datenzugriffssequenz besteht darin, zuerst zu überprüfen, ob eine Tabellenzeile vorhanden ist. Wenn die Zeile vorhanden ist, aktualisieren Sie sie. Andernfalls erstellen Sie die Zeile. Sie können diese Sequenz effizienter gestalten, indem Sie einen einzelnen API-Aufruf des Upsert-Vorgangs verwenden.
Weitere Informationen finden Sie unter Verwenden von Upsert zum Erstellen oder Aktualisieren eines Datensatzes.
Important
Für die in alternate_key verwendeten Spalten muss in Dataverse ein alternativer Schlüssel für die Tabelle konfiguriert sein. Definieren Sie alternative Schlüssel in den Metadaten der Tabelle über das Power Apps Maker-Portal oder einen Dataverse-API-Aufruf. Ohne einen konfigurierten alternativen Schlüssel lehnt Dataverse Upsert-Anforderungen mit einem Fehler von 400 ab.
Verwenden Sie client.records.upsert(), um Datensätze zu erstellen oder zu aktualisieren, die durch alternative Schlüssel identifiziert werden. Wenn der Schlüssel einem vorhandenen Datensatz entspricht, aktualisiert die Methode den Datensatz. Andernfalls wird der Datensatz erstellt. Ein einzelnes Element verwendet eine PATCH-Anfrage, während mehrere Elemente die UpsertMultiple Sammelaktion verwenden.
from PowerPlatform.Dataverse.models.upsert import UpsertItem
# Upsert a single record
client.records.upsert("account", [
UpsertItem(
alternate_key={"accountnumber": "ACC-001"},
record={"name": "Contoso Ltd", "telephone1": "555-0100"},
)
])
# Upsert multiple records (uses UpsertMultiple bulk action)
client.records.upsert("account", [
UpsertItem(
alternate_key={"accountnumber": "ACC-001"},
record={"name": "Contoso Ltd"},
),
UpsertItem(
alternate_key={"accountnumber": "ACC-002"},
record={"name": "Fabrikam Inc"},
),
])
# Composite alternate key (multiple columns identify the record)
client.records.upsert("account", [
UpsertItem(
alternate_key={"accountnumber": "ACC-001", "address1_postalcode": "98052"},
record={"name": "Contoso Ltd"},
)
])
# Plain dict syntax (no import needed)
client.records.upsert("account", [
{
"alternate_key": {"accountnumber": "ACC-001"},
"record": {"name": "Contoso Ltd"},
}
])
Datenrahmen
Das SDK stellt Pandas Wrapper für alle CRUD-Vorgänge über den client.dataframe Namespace bereit. Diese Wrapper verwenden die DataFrame- und Series-APIs von Pandas für Eingabe und Ausgabe.
Note
client.dataframe.get() ist veraltet. Verwenden Sie die ga-Muster, die in den folgenden Abschnitten gezeigt werden.
import pandas as pd
from PowerPlatform.Dataverse.models.filters import col
# Query records as a single DataFrame (GA builder pattern)
df = (client.query.builder("account")
.select("name", "telephone1")
.where(col("statecode") == 0)
.execute()
.to_dataframe())
print(f"Found {len(df)} accounts")
# Limit results with top for large tables
df = client.query.builder("account").select("name").top(100).execute().to_dataframe()
# Create records from a DataFrame (returns a Series of GUIDs)
new_accounts = pd.DataFrame([
{"name": "Contoso", "telephone1": "555-0100"},
{"name": "Fabrikam", "telephone1": "555-0200"},
])
new_accounts["accountid"] = client.dataframe.create("account", new_accounts)
# Update records from a DataFrame (id_column identifies the GUID column)
new_accounts["telephone1"] = ["555-0199", "555-0299"]
client.dataframe.update("account", new_accounts, id_column="accountid")
# Clear a field by setting clear_nulls=True (by default, NaN/None fields are skipped)
df = pd.DataFrame([{"accountid": new_accounts["accountid"].iloc[0], "websiteurl": None}])
client.dataframe.update("account", df, id_column="accountid", clear_nulls=True)
# Delete records by passing a Series of GUIDs
client.dataframe.delete("account", new_accounts["accountid"])
# SQL query directly to DataFrame (supports JOINs, aggregates, GROUP BY)
df = client.dataframe.sql(
"SELECT a.name, COUNT(c.contactid) as contacts "
"FROM account a "
"JOIN contact c ON a.accountid = c.parentcustomerid "
"GROUP BY a.name"
)
Hochladen von Dateien in Dataverse
Das folgende Beispiel zeigt, wie Sie eine Datei mit dem Namen document.pdf in die Spalte „Datei“ mit dem Namen new_Document eines Kontodatensatzes hochladen. Das SDK für Python behandelt automatisch Dateiabschnitte für Dateien, die größer als 128 MB sind.
# Upload a file to a record
client.files.upload(
"account",
account_id,
"new_Document",
"/path/to/document.pdf",
)
Tip
Wenn die Dateispalte nicht vorhanden ist, erstellt das SDK sie automatisch.
Batchvorgänge
Verwenden Sie client.batch, um mehrere Vorgänge in einer einzigen HTTP-Anfrage zu senden. Der Batch-Namespace entspricht client.records, client.tables und client.query.
# Build a batch request and add operations
batch = client.batch.new()
batch.records.create("account", {"name": "Contoso"})
batch.records.create("account", [{"name": "Fabrikam"}, {"name": "Woodgrove"}])
batch.records.update("account", account_id, {"telephone1": "555-0100"})
batch.records.delete("account", old_id)
batch.records.retrieve("account", account_id, select=["name"], expand=["primarycontactid"]) # single record with expand
batch.records.list( # multi-record, single page
"account",
filter="statecode eq 0",
select=["name"],
orderby=["name asc"],
top=50,
)
result = batch.execute()
for item in result.responses:
if item.is_success:
print(f"[OK] {item.status_code} entity_id={item.entity_id}")
else:
print(f"[ERR] {item.status_code}: {item.error_message}")
Transaktionsänderungenet
Alle Vorgänge in einem Changeset werden entweder erfolgreich ausgeführt oder gemeinsam zurückgesetzt.
batch = client.batch.new()
with batch.changeset() as cs:
lead_ref = cs.records.create("lead", {"firstname": "Ada"})
contact_ref = cs.records.create("contact", {"firstname": "Ada"})
cs.records.create("account", {
"name": "Babbage & Co.",
"originatingleadid@odata.bind": lead_ref,
"primarycontactid@odata.bind": contact_ref,
})
result = batch.execute()
print(f"Created {len(result.entity_ids)} records atomically")
Tabellenmetadaten und SQL-Abfragen in einem Batch
batch = client.batch.new()
batch.tables.create("new_Product", {"new_Price": "decimal", "new_InStock": "bool"})
batch.tables.add_columns("new_Product", {"new_Rating": "int"})
batch.tables.get("new_Product")
batch.query.sql("SELECT TOP 5 name FROM account")
result = batch.execute()
Bei Fehler fortfahren
Versuchen Sie alle Vorgänge auch dann, wenn ein Fehler auftritt.
result = batch.execute(continue_on_error=True)
print(f"Succeeded: {len(result.succeeded)}, Failed: {len(result.failed)}")
for item in result.failed:
print(f"[ERR] {item.status_code}: {item.error_message}")
DataFrame-Integration
Führen Sie pandas DataFrames direkt einem Batch zu.
import pandas as pd
batch = client.batch.new()
# Create records from a DataFrame
df = pd.DataFrame([{"name": "Contoso"}, {"name": "Fabrikam"}])
batch.dataframe.create("account", df)
# Update records from a DataFrame
updates = pd.DataFrame([
{"accountid": id1, "telephone1": "555-0100"},
{"accountid": id2, "telephone1": "555-0200"},
])
batch.dataframe.update("account", updates, id_column="accountid")
# Delete records from a Series
batch.dataframe.delete("account", pd.Series([id1, id2]))
result = batch.execute()
Ein vollständiges Batchbeispiel finden Sie unter examples/advanced/batch.py.