This project demonstrates how to perform bulk create and delete operations in Microsoft Dataverse using the Web API $batch endpoint.
- Azure AD authentication using MSAL
- Batch create and delete for Dataverse tables
- Error handling for partial failures
- Configurable via
.env
file
auth.py
: Handles Azure AD authentication using MSAL and environment variablesbatch_builder.py
: Builds robust $batch payloads for Dataverse create/delete operationsdataverse_client.py
: Sends batch requests, parses responses, and handles errorsmain.py
: CLI entry point for local testing and demonstrationBatchDataverseFunction/__init__.py
: Azure Function entry point (uses modularized code)
- Install dependencies:
pip install -r requirements.txt
- Copy
.env.example
to.env
and fill in your Azure/Dataverse credentials. - To test locally (CLI):
python main.py
- To run as an Azure Function:
- Make sure you have Azure Functions Core Tools installed.
- Start the function host:
func start
- POST an Excel file to the function endpoint (see below).
- Python 3.8+
requests
,msal
,python-dotenv
,openpyxl
,azure-functions
Run the sample with:
python main.py
This will load an Excel file, map columns, and perform batch create operations in Dataverse.
Start the function host:
func start
Then upload your Excel file using Postman or curl:
curl -X POST http://localhost:7071/api/BatchDataverseFunction -F "file=@test/PowerPlatform_All_Users_Synthetic.xlsx"
The function will log progress and return a JSON result for each record.
- All values for string columns are now explicitly cast to strings to avoid Dataverse type errors.
- Only batch creation (insert) is supported in this version. Batch delete/update is planned.
- 400 Bad Request / Edm.String error: Ensure all values for string columns are sent as strings (this is now handled automatically).
- 404 Resource not found: Check your table/entity set name and column logical names.
- 401/403 Unauthorized: Ensure your app registration has correct permissions and is added as an Application User in Dataverse.
This project is licensed under the MIT License - see the LICENSE file for details.