A lightweight, reliable, and metadata-aware configuration engine for managing Microsoft Dataverse / Dynamics 365 data using a clean and declarative TOML syntax (version 1.0.0).
The goal of this project is to make configuration updates predictable, repeatable, and environment-agnostic — without relying on manual edits or fragile scripts.
The engine preserves execution order, validates operations against Dataverse metadata, and provides deterministic behavior across environments.
It is available through dedicated host integrations for:
- XrmToolbox (interactive execution) → Go to documentation
- PACX/Greg.Xrm.Command (CI/CD scenarios) → Go to documentation
In complex Dataverse projects, configuration data is often:
-
manually edited
-
inconsistently aligned across environments
-
difficult to promote safely
-
managed through fragile scripts
TOML Config Manager introduces a declarative approach that:
-
preserves execution order
-
validates operations against metadata
-
provides per-operation observability and structured diagnostics
-
supports both interactive and CI/CD execution models
The solution is composed of three logical layers.
Responsible for:
-
TOML parsing
-
Operation validation
-
Metadata-driven type resolution
-
Deterministic execution pipeline
-
Structured logging
The engine is host-agnostic and can be embedded in different execution contexts.
Provides:
-
Interactive UI
-
Operation selection
-
Per-operation retry
-
Visual log inspection
Designed for controlled manual alignment scenarios.
Provides:
-
Non-interactive execution
-
CI/CD integration
-
Deterministic pipeline-friendly behavior
Designed for automated environment promotion scenarios.
Operations are executed sequentially in the exact order defined in the TOML file.
-
Execution order is strictly preserved.
-
No reordering or implicit grouping occurs.
Each TOML Operation is processed independently:
-
A failure does not stop subsequent operations.
-
Results are tracked per operation.
-
Detailed logs are generated for diagnostics.
This model allows:
-
Targeted correction scenarios
-
Clear error visibility
-
Deterministic but resilient execution
Host behavior may differ in how operations are triggered (interactive vs automated), but the core execution logic remains consistent.
All operations within a run share the same:
-
Source connection context
-
Target connection context
Connections are resolved once at the beginning of execution and reused across all operations unless explicitly changed by the host.
To reduce round-trips and ensure consistent validation, the engine caches Dataverse metadata during execution.
This includes column metadata.
The cache is scoped to the execution context.
The TOML syntax is used to describe the following operations:
createupsertreplacedelete
Each operation can describe:
- the target table
- the matching criteria
- the row values
- optional ignored fields
All in a simple, human‑readable TOML format.
| Property | Type | Description |
|---|---|---|
type |
string |
The operation type to execute (create, upsert, replace, delete) |
table |
string |
The logical name of the target Dataverse table |
match_on |
List<string> |
Field names used to identify/match existing records |
rows |
List<List<string>> |
Multiple rows of values corresponding to match_on fields |
ignore_fields |
List<string> |
Fields to exclude when copying data |
fields |
List<string> |
Field names to set on the record |
values |
List<string> |
Values corresponding to fields |
| type | table |
match_on |
rows |
fields |
values |
ignore_fields |
File/Image support |
|---|---|---|---|---|---|---|---|
create |
✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ |
replace |
✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
upsert |
✅ | ✅ | ✅ | ❌ | ❌ | ⚪ Optional | ✅ |
delete |
✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
Creates a new record if no match exists; updates the existing record otherwise. This operation is designed for environment‑to‑environment alignment: field values are copied from the source environment to the target environment. If a field is null in the source environment, the corresponding field in the target will be explicitly cleared to ensure strict alignment.
Required properties:
table– Target table namematch_on– Fields used to match recordsrows– Values to match againstmatch_on
Optional properties:
ignore_fields– Fields to exclude from copy
match_onand each entry inrowsmust contain the same number of elements.match_onmust reference stable identifier columns. File and image columns are not supported in match_on criteria.- Empty strings ("") inside
rowsare interpreted as null values during the record lookup.
Example:
[[operation]]
type = "upsert"
table = "contact"
match_on = ["emailaddress1"]
rows = [["john@contoso.com"]]
ignore_fields= ["createdon", "modifiedon"]
Updates an existing record matching specific criteria.
Required properties:
table– Target table namematch_on– Fields used to locate the recordrows– Values to match againstmatch_onfields– Fields to updatevalues– New values for thefields
match_onand each entry inrowsmust have matching cardinality.match_onmust reference stable identifier columns. File and image columns are not supported in match_on criteria.fieldsandvaluesmust contain the same number of elements.- Empty strings ("") inside
rowsandvaluesare interpreted as null values during both record lookup and update execution.
Example:
[[operation]]
type = "replace"
table = "account"
match_on = ["accountnumber","name"]
rows = [["ACC001","Contoso"]]
fields = ["name"]
values = ["Contoso Ltd"]
Creates a new record in the target table.
Required properties:
table– Target table namefields– List of field names to populatevalues– Corresponding values for each field
fieldsandvaluesmust contain the same number of elements.- Empty strings ("") inside
valuesare interpreted as null values when creating a record.
Example:
[[operation]]
type = "create"
table = "account"
fields = ["name", "accountnumber"]
values = ["Contoso", "ACC001"]
Deletes a record matching specific criteria from the target environment.
Required properties:
table– Target table namematch_on– Fields used to locate the recordrows– Values to match againstmatch_on
match_onand each entry inrowsmust contain the same number of elements.match_onmust reference stable identifier columns. File and image columns are not supported in match_on criteria.- Empty strings ("") inside
rowsare interpreted as null values during the record lookup.
Example:
[[operation]]
type = "delete"
table = "account"
match_on = ["accountnumber"]
rows = [["ACC001"]]
The engine supports synchronization of Dataverse file and image columns within upsert and replace operations.
In upsert operations the file/image content is copied from the source environment to the target environment.
If a file/image column is null in the source environment, it will be nulled in the target environment as well.
File/Image fields can be ignored if explicitly listed in the ignore_fields property.
In replace operations the file/image content is set based on the provided value.
File and image values can be specified using a scheme-based syntax inside values:
base64:<content>|<filename>
file:<path>|<filename>
values = [
"base64:AAABBBCCC...|document.pdf"
]
values = [
"file:./assets/logo.png|logo.png"
]
Absolute paths are used as-is.
Relative paths are resolved against a base path:
-
If a base path is explicitly defined, it is used for resolution.
-
If no base path is defined, the current working directory is used.
This ensures consistent path handling across different execution contexts.
The base path is always logged at runtime to ensure transparency.
The tool enforces deterministic formats to avoid timezone issues and ambiguous parsing.
yyyy-MM-dd
yyyy-MM-ddTHH:mm:ss
yyyy-MM-ddTHH:mm:ssZ
yyyy-MM-ddTHH:mm:ss±hh:mm
Invalid formats produce clear, actionable error messages.
Feedback, feature suggestions, and issue reports are welcome.
Please open an issue in the repository to discuss improvements or report unexpected behavior.
This project is licensed under the MIT License.
This project relies on the excellent open-source library:
- Tomlyn by Alexandre Mutel, a .NET TOML parser licensed under BSD-2-Clause. https://github.com/xoofx/Tomlyn
See THIRD-PARTY-NOTICES.md for full license details.