DEV Community

Cover image for Tables, EDTs, Base Enums, and Relations
Hima Bindu
Hima Bindu

Posted on

Tables, EDTs, Base Enums, and Relations

X++ tables, EDTs, base enums, and relations
Yesterday we covered variables, classes, and methods — the language building blocks. Today we look at how X++ actually organizes and stores persistent data: tables, the extended data types (EDTs) that give fields meaning, the base enums that restrict a field to valid values, and the relations that connect tables to each other.

  1. Tables: rows of persistent data A table in X++ (and the AOT — Application Object Tree) is a database table with a strongly-typed structure layered on top. Every table maps to a SQL table under the hood, but you interact with it through X++ objects, never raw SQL. Two examples you'll recognize immediately:

SalesTable — one row per sales order
CustTable — one row per customer
Each table is made up of fields, and — critically — every field's type in F&O is almost never a raw primitive. It's an EDT.

  1. Extended data types (EDTs): reusable, labeled fields An EDT wraps a primitive type (str, int, real, and so on) and adds metadata: a label, a help string, a display format, string length, and — importantly — it can carry a relation to another table. Once defined, the same EDT gets reused everywhere that concept appears.

EDT: CustAccount
extends: str
label: "Customer account"
string size: 20
Because CustAccount is defined once as an EDT, both SalesTable and CustTable can use it — and both fields carry the exact same label, length, and validation without you retyping any of it. This is the reason F&O feels consistent everywhere: the same field looks and behaves identically across every form and table it appears on.

  1. Base enums: a fixed list of valid values A base enum restricts a field to one of a predefined set of options — no free text, no invalid states. Think of it as a strongly-typed dropdown baked into the data model:

enum SalesStatus
{
Backorder,
Delivered,
Invoiced,
Canceled
}
A field typed as SalesStatus can only ever hold one of those four values. This is why you'll rarely see a status field implemented as plain text in F&O — enums make invalid states unrepresentable, and they're what powers the dropdown lists you see in forms.

  1. Relations: connecting tables together A relation tells X++ how two tables' fields correspond to each other — which field on one table matches which field on another. This is what lets a join, a lookup, or a foreign-key-style validation work automatically instead of you writing the join logic by hand every time.

Here's how SalesTable and CustTable connect: SalesTable stores a customer's account number in its CustAccount field (an EDT). CustTable uses that same EDT as its primary key, AccountNum. The relation is the metadata that says "these two fields refer to the same customer."

CustAccount field.
Because that relation exists, a query can join the two tables directly:

select salesTable
join custTable
where custTable.AccountNum == salesTable.CustAccount;
Why this matters: relations aren't just documentation — Application Explorer, form lookups, and the query framework all read this metadata to auto-generate joins, foreign-key validation, and drop-down lookups. Define the relation once, and every tool built on top of X++ understands how your tables connect.
Key takeaways
Tables store persistent data — one row per record, built from strongly-typed fields.
EDTs wrap primitives with a label, format, and length, so the same field behaves identically everywhere it's reused.
Base enums restrict a field to a fixed set of valid values — no invalid states possible.
Relations define how tables' fields connect, powering automatic joins, lookups, and validation.

Next up (Day 3): form patterns and building blocks — how X++ turns tables into the screens users actually interact with.

Top comments (0)