Dynamics 365 CE(CRM) ↔ F&O: Comparison Cheat Sheet

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

AspectCE (Customer Engagement / Dataverse)F&O (Finance & Operations)
PurposeCRM workloads (sales, service, marketing)ERP (finance, supply chain, production)
RuntimeMulti-tenant SaaSAOS server per environment
CodeC#, JavaScript, Power AutomateX++ (compiled to IL/CIL), SysOperation
Dev machineBrowser onlyDevBox VM (Tier-1)

Data Layer

ConceptCEF&O
TableDataverse tableAOT table (compiled)
Field/ColumnDataverse columnTable field (often via EDT)
Add field to Microsoft OOB tableDirect in solutionTable extension (fields live in the extension but become real columns)
Custom tableCreate in solutionCreate table and add fields directly (no extension)
Reusable typeEDT (Extended Data Type)
RelationsN:1, 1:N, N:NTable relations, RefRecId, enums
KeysPrimary, alternatePrimary keys, indexes (clustered/nonclustered)

UI Layer

ConceptCEF&O
Form/pageModel-driven formForm with patterns (Detail, ListPage, Workspace)
View/listViewsGrids, queries
Custom controlPCFExtensible Control (TS/JS, contract-bound)
Client scriptingJavaScript via Xrm.*No Xrm; optional Extensible Control; business logic in X++
Simple rulesBusiness rulesForm methods + validate/modified

Logic & Pipeline

TopicCEF&O
Server hooksPlugins (C#) on staged pipelineCoC on specific methods:
  validateField,
  modifiedField,
  validateWrite,
  insert/update/delete
Flow/automationPower AutomateBatch/SysOperation, Business events
TransactionManaged by DataversettsBegin/ttsCommit; checkFailed() or returning false cancels save
Execution orderPreValidation → PreOperation → PostOperationOne chain per method; next <method>() calls base/previous extension (sequential)

Plugin Stages (CE) vs CoC Methods (F&O)

CE plugin stageCE plugin
When it runs
F&O
CoC hook
F&O
Purpose
PreValidationBefore DB txn, before main pipelinevalidateField(), modifiedField()Field-level checks and reactions
PreOperationInside txn, before writevalidateWrite()Row-level gate; return false to cancel
Operationinsert() / update() (ttsBegin/ttsCommit)Actual persistence logic
PostOperationAfter write, still in txnPost-handlers or post-update()Side-effects that need the same txn
Async (Post)After commit, asyncBatch/SysOperation, Business eventsOut-of-band processing

F&O Save Sequence (Simplified)

StepMeaning
validateField()Is the new field value allowed?
modifiedField()React to change (defaults, lookups, recalcs)
validateWrite()Gate before save (create & update)
ttsBegin → insert()/update() → ttsCommitTransactional persistence
Delete pathvalidateDelete()delete()

Labels & Localization

AspectCEF&O
WhereSolution labelsLabel files (.ald) per model/language
UsageCaptions, choicesAll text: captions, errors, tooltips; referenced as @Model:LabelId
StoragePlatform-managedCompiled resources in the package

Integration

NeedCEF&O
APIDataverse Web APIOData via Data Entities; custom services
Files/ETLDataflows / ADFDMF (CSV/Package), Electronic Reporting, Recurring Integrations
EventsWebhooks, pluginsBusiness events, Batch

Reporting & Analytics

CEF&O
Power BI, views, Advanced FindSSRS (DP/Contract/Report), Power BI, Inquiry pages, ER

Security

CEF&O
Roles, privileges, teamsRole → Duty → Privilege → Entry point (+ table permissions)

ALM & Environments

CEF&O
Dev/Test/Prod orgs; solution movesDevBox for code, Build server, Tier-2+ Sandboxes/Prod via LCS; deployable packages

Extensible Control vs PCF

TopicPCF (CE)Extensible Control (F&O)
HostDataverse formF&O form control
Data accesscontext.parametersBound properties + control contract
DeploySolution importIn model/package; deploy via build/LCS
RoleCan carry logicUI widget only; business rules in X++

Typical Patterns (with Examples)

TaskCE wayF&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