Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article illustre un exemple de code qui utilise le Kit de développement logiciel (SDK) pour utiliser des données et des métadonnées Dataverse. Avant de continuer, veillez à lire Bien démarrer.
Opérations de base
Voici un exemple de code qui fonctionne sur la table de compte.
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)
Gestionnaire de contexte
Le Gestionnaire de contexte gère le nettoyage automatique et le regroupement de connexions HTTP. Utilisez la syntaxe suivante pour tirer parti du Gestionnaire de contexte.
with DataverseClient("https://<myorg>.crm.dynamics.com", credential) as client:
Le code de travail suivant montre comment utiliser le Gestionnaire de contextes.
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
Opérations en bloc
Voici quelques exemples qui effectuent des opérations en bloc.
# 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)
L’exemple suivant crée plusieurs comptes. Transmettez une liste de charges utiles à create(logical_name, payloads) pour appeler l'action liée à la collection Microsoft.Dynamics.CRM.CreateMultiple. La méthode retourne list[str] des ID d’enregistrement créés.
# 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})
Pour plus d’informations sur les opérations en bloc :
- Retourne
None(identique à la mise à jour unique) pour maintenir la cohérence sémantique. - Le mode diffusion ou par enregistrement est déterminé selon que le paramètre
changesest un dictionnaire ou une liste. - L’attribut de clé primaire est ajouté automatiquement lors de la création des cibles de l’action UpdateMultiple.
- Si une charge utile omet @odata.type, le SDK l’étiquette automatiquement (la recherche de nom logique mise en cache).
- La réponse inclut uniquement les ID : le KIT de développement logiciel (SDK) retourne ces chaînes GUID.
- La création d’un seul enregistrement retourne une liste comprenant un seul élément de GUIDs.
- La recherche
@odata.typede métadonnées est effectuée une fois par jeu d’entités (mis en cache en mémoire).
Upsert (création et mise à jour)
Une séquence d’accès aux données courante consiste à vérifier d’abord si une ligne de table existe. Si la ligne existe, mettez-la à jour. Sinon, créez la ligne. Vous pouvez rendre cette séquence plus efficace en utilisant un seul appel d’API de l’opération Upsert.
Pour plus d’informations, consultez Utiliser Upsert pour créer ou mettre à jour un enregistrement.
Important
La table doit avoir une autre clé configurée dans Dataverse pour les colonnes utilisées dans alternate_key. Définissez d'autres clés dans les métadonnées de la table via le portail Power Apps maker ou un appel d'API Dataverse. Sans clé secondaire configurée, Dataverse rejette les requêtes upsert avec une erreur 400.
Permet client.records.upsert() de créer ou de mettre à jour des enregistrements identifiés par d’autres clés. Lorsque la clé correspond à un enregistrement existant, la méthode met à jour l’enregistrement. Sinon, il crée l’enregistrement. Un seul élément utilise une requête PATCH tandis que plusieurs éléments utilisent l’action UpsertMultiple en bloc.
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"},
}
])
Cadres de données
Le SDK fournit des wrappers Pandas pour toutes les opérations CRUD via l’espace de noms client.dataframe. Ces wrappers utilisent les API DataFrame et Series de pandas pour les entrées et les sorties.
Note
client.dataframe.get() est déconseillé. Utilisez les modèles en disponibilité générale indiqués dans les sections suivantes.
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"
)
Charger des fichiers dans Dataverse
L’exemple suivant montre comment charger un fichier nommé document.pdf dans la colonne Fichier nommée new_Document d’un enregistrement de compte. Le Kit de développement logiciel (SDK) pour Python gère automatiquement la segmentation des fichiers pour les fichiers de plus de 128 Mo.
# Upload a file to a record
client.files.upload(
"account",
account_id,
"new_Document",
"/path/to/document.pdf",
)
Tip
Si la colonne de fichier n’existe pas, le Kit de développement logiciel (SDK) le crée automatiquement.
Opérations par lots
Permet client.batch d’envoyer plusieurs opérations dans une requête HTTP. L’espace de noms batch reflète client.records, client.tableset 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}")
Ensemble de modifications transactionnelles
Toutes les opérations d’un jeu de modifications réussissent ou sont annulées ensemble.
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")
Métadonnées de table et requêtes SQL dans un lot
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()
Continuer malgré l’erreur
Essayez toutes les opérations même en cas d’échec.
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}")
Intégration de DataFrame
Importez directement des DataFrames de pandas dans un lot.
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()
Pour obtenir un exemple de lot complet, consultez examples/advanced/batch.py.
Informations connexes
- Personnaliser des tables et des colonnes
- Données de requête
- Exemples de code SDK pour Python
- SDK pour Python README