Audience: CE developers moving into F&O or working across both.
Goal: map concepts, components, and patterns one-to-one with concise examples.
Big Picture
Aspect | CE (Customer Engagement / Dataverse) | F&O (Finance & Operations) |
Purpose | CRM workloads (sales, service, marketing) | ERP (finance, supply chain, production) |
Runtime | Multi-tenant SaaS | AOS server per environment |
Code | C#, JavaScript, Power Automate | X++ (compiled to IL/CIL), SysOperation |
Dev machine | Browser only | DevBox VM (Tier-1) |
Data Layer
Concept | CE | F&O |
Table | Dataverse table | AOT table (compiled) |
Field/Column | Dataverse column | Table field (often via EDT) |
Add field to Microsoft OOB table | Direct in solution | Table extension (fields live in the extension but become real columns) |
Custom table | Create in solution | Create table and add fields directly (no extension) |
Reusable type | — | EDT (Extended Data Type) |
Relations | N:1, 1:N, N:N | Table relations, RefRecId, enums |
Keys | Primary, alternate | Primary keys, indexes (clustered/nonclustered) |
UI Layer
Concept | CE | F&O |
Form/page | Model-driven form | Form with patterns (Detail, ListPage, Workspace) |
View/list | Views | Grids, queries |
Custom control | PCF | Extensible Control (TS/JS, contract-bound) |
Client scripting | JavaScript via Xrm.* | No Xrm ; optional Extensible Control; business logic in X++ |
Simple rules | Business rules | Form methods + validate/modified |
Logic & Pipeline
Topic | CE | F&O |
Server hooks | Plugins (C#) on staged pipeline | CoC on specific methods:
validateField ,
modifiedField ,
validateWrite , insert/update/delete |
Flow/automation | Power Automate | Batch/SysOperation, Business events |
Transaction | Managed by Dataverse | ttsBegin/ttsCommit ; checkFailed() or returning false cancels save |
Execution order | PreValidation → PreOperation → PostOperation | One chain per method; next <method>() calls base/previous extension (sequential) |
Plugin Stages (CE) vs CoC Methods (F&O)
CE plugin stage | CE plugin When it runs | F&O CoC hook | F&O Purpose
|
PreValidation | Before DB txn, before main pipeline | validateField() , modifiedField() | Field-level checks and reactions |
PreOperation | Inside txn, before write | validateWrite() | Row-level gate; return false to cancel |
Operation | — | insert() / update() (ttsBegin/ttsCommit ) | Actual persistence logic |
PostOperation | After write, still in txn | Post-handlers or post-update() | Side-effects that need the same txn |
Async (Post) | After commit, async | Batch/SysOperation, Business events | Out-of-band processing |
F&O Save Sequence (Simplified)
Step | Meaning |
validateField() | Is the new field value allowed? |
modifiedField() | React to change (defaults, lookups, recalcs) |
validateWrite() | Gate before save (create & update) |
ttsBegin → insert()/update() → ttsCommit | Transactional persistence |
Delete path | validateDelete() → delete() |
Labels & Localization
Aspect | CE | F&O |
Where | Solution labels | Label files (.ald ) per model/language |
Usage | Captions, choices | All text: captions, errors, tooltips; referenced as @Model:LabelId |
Storage | Platform-managed | Compiled resources in the package |
Integration
Need | CE | F&O |
API | Dataverse Web API | OData via Data Entities; custom services |
Files/ETL | Dataflows / ADF | DMF (CSV/Package), Electronic Reporting, Recurring Integrations |
Events | Webhooks, plugins | Business events, Batch |
Reporting & Analytics
CE | F&O |
Power BI, views, Advanced Find | SSRS (DP/Contract/Report), Power BI, Inquiry pages, ER |
Security
CE | F&O |
Roles, privileges, teams | Role → Duty → Privilege → Entry point (+ table permissions) |
ALM & Environments
CE | F&O |
Dev/Test/Prod orgs; solution moves | DevBox for code, Build server, Tier-2+ Sandboxes/Prod via LCS; deployable packages |
Extensible Control vs PCF
Topic | PCF (CE) | Extensible Control (F&O) |
Host | Dataverse form | F&O form control |
Data access | context.parameters | Bound properties + control contract |
Deploy | Solution import | In model/package; deploy via build/LCS |
Role | Can carry logic | UI widget only; business rules in X++ |
Typical Patterns (with Examples)
Task | CE way | F&O way |
Add field to OOB table |
New column in solution |
Table extension + field (via EDT); Form extension to show it |
Required-field validation |
Business rule or PreOp plugin |
CoC on validateWrite() ; checkFailed("@My:Label") + return false |
Lookup |
Lookup column |
EDT with Relation + ReferenceGroup control (auto-lookup) |
Background job |
Flow or plugin (async) |
SysOperation (contract/service/controller) + batch |
Export vendors |
Web API / Dataflow |
DMF Export VendVendorV2Entity (CSV) |
Custom UI widget |
PCF |
Extensible Control (TS/JS) |
Mini X++ Example: CoC Required Field
// HX_VendTable_ValidateWrite_CoC
// ----------------
// Enforces non-empty HX_ExternalRefId on vendor save.
//
// Sep 20, 2025: Created by Forrest Zhang for Bootcamp D01
[ExtensionOf(tableStr(VendTable))]
final class HX_VendTable_ValidateWrite_CoC
{
public boolean validateWrite()
{
boolean ok = next validateWrite();
if (!ok) return ok;
if (this.(fieldNum(VendTable, HX_ExternalRefId)) == '' || this.(fieldNum(VendTable, HX_ExternalRefId)) == null)
{
checkFailed("@HX:ExternalRefIdRequired");
return false;
}
return true;
}
}
Quick Answers
- Do fields in a table extension become real columns? Yes—on Microsoft OOB tables. On your own custom table, add fields directly.
- Is there
validateCreate()
? No. Use validateWrite()
for create/update; use CoC on insert()
for create-only logic.
- AOS & CIL? AOS = Application Object Server (runtime). X++ compiles to .NET IL/CIL; AOS executes it.
Author: Forrest Zhang — Dynamics 365 CE & F&O Developer
No comments:
Post a Comment