When working with Dynamics 365 Finance & Operations (D365FO), the standard approach to data access is through X++ query classes — select statements, QueryRun, SysDa, and the like. These abstractions handle field mappings, security, cross-company filtering, and valid-time-state logic automatically. They're the right tool almost every time.
But "almost" isn't "always." There are cases where you need to step outside those guardrails and execute raw SQL against the runtime database: bulk data corrections during a migration, performance-critical operations that the query framework can't optimize well, or diagnostic tooling that needs to inspect metadata tables directly. For those situations, D365FO exposes a set of classes that let you run SQL statements from X++ code.
This post walks through building a reusable utility class that wraps that capability cleanly, with proper error handling and a clear contract.
Why You'd Want This (and Why You Usually Wouldn't)
Before we write a single line, some honest caveats. Direct SQL in D365FO bypasses several things the framework normally does for you:
- Table-level security and record-level security (RLS) are not enforced.
xRecordevents (onInserting,onUpdated, etc.) do not fire.- Database logging and change tracking won't capture the operation.
- Valid-time-state filtering is your responsibility.
- Cross-company isolation is your responsibility.
If any of those matter for your use case, stay with the standard query framework. Direct SQL is a power tool, not a daily driver.