The X++ delta — what changed in the language, runtime and data-access model

The source and target language are both X++, so this chapter is the delta — Chain of Command semantics, attribute-driven extensions, the removal of client-side X++, RunBase versus SysOperation, ttsbegin/ttscommit nesting, temporary table flavours, RecId and DataAreaId invariants, and the performance patterns that changed because the database moved to a cloud-hosted SQL service.

What you will be able to do

Introduction

This chapter is unusual in the context of this site. Every other source system has a different language — ABAP, C, PL/SQL, L4G, SuiteScript. AX 2012 and D365 both use X++. The developer's task is not to learn a new language but to learn what changed in the one they already know.

Chain of Command: the mechanics

A Chain of Command extension is a class decorated with [ExtensionOf(classStr(TargetClass))] (or the equivalent for tables, forms and data entities). The class must be marked final — it cannot itself be extended by another class.

The removal of client-side X++

Server tier (the AOS) — batch jobs, posting logic, data access Client tier (the rich client process) — form interaction, WinAPI calls, COM automation, local file access

RunBase versus SysOperation

public Object dialog() { Dialog dlg = super(); dlgCustomerId = dlg.addField(extendedTypeStr(CustAccount)); return dlg; }

Transaction scope: ttsbegin and ttscommit

X++ transactions are reference-counted. Each ttsbegin increments a nesting counter; each ttscommit decrements it. Only when the counter reaches zero does the actual SQL COMMIT execute. A ttsabort at any nesting depth discards the entire transaction and throws an exception.

Temporary tables: InMemory versus TempDB

Heap-allocated in the AOS process memory Scoped to the variable that declares the buffer Cannot be joined in SQL (the database does not know they exist) Cannot back a form data source in the D365 web client Best for: small lookup sets, intermediate computation within a single method, containers of parameters

Performance patterns, RecId and DataAreaId

RecId is a 64-bit integer, unique per table, assigned by the system at insert time. It is the surrogate primary key and the FK wire in most relationships. AX 2012 and D365 share this invariant. The delta for migrated code:

Before-and-after code examples

```xpp // In the CUS layer, the entire method body is replaced: boolean validateWrite() { boolean ret; ret = super(); // calls SYS layer version

Knowledge check

Summary

The language is still X++. The select family, the type system, the class hierarchy, the table model, the transaction primitives — all of these are recognisable. What changed is not the vocabulary but the contract: you extend rather than replace, you run server-side rather than client-side, you respect cloud-SQL performance constraints…