Computed columns in D365 F&O data entities (vs virtual fields)
In a D365 F&O data entity, a computed column is a SQL column generated by a static X++ method. When to use it over a virtual field, code and pitfalls.
The short answer
In Dynamics 365 Finance & Operations, a data entity computed column is an unmapped field whose value SQL Server calculates. You create it with an "Unmapped" field whose IsComputedField property is Yes, and a static X++ method that returns the SQL expression. That method is only called when the database is synchronised: at run time, SQL computes the value directly in the entity view.
The other option is the virtual field (IsComputedField = No): its value is calculated in X++, row by row, for example in postLoad. Microsoft recommends computed columns where possible, because they are computed at the SQL Server level. Virtual fields support neither search nor filtering.
Note: if you are looking for a "calculated field" in the sense of a formula on a form, that is usually a display method; this article covers data entities, used for import/export, OData and integrations.
Computed column or virtual field: how to choose?
- Computed column: value produced by a computed column of the SQL view; read directly from the view; ideal for reads and exports; filterable.
- Virtual field: not persisted, read and written by X++ code; reserve it for values that cannot be expressed in SQL; no search or filter.
- On writes, both go through X++ (for example mapEntityToDataSource) that splits the incoming value into the real fields of the data sources.
Impact on export performance: Microsoft advises against postLoad, which forces the export through the staging table so the method can be called for each row. Prefer a computed column when SQL can produce the value.
Creating a computed column step by step
The Microsoft Learn example adds a NameAndAddress field to the FMCustomerEntity entity, concatenating name and address:
- In the entity designer, right-click Fields > New > String Unmapped Field; name it NameAndAddress.
- Leave IsComputedField set to Yes and set the method property (DataEntityView Method / ComputedFieldMethod) to the name of the static method.
- Create that static method; it builds the SQL expression with the SysComputedColumn class (returnField, returnLiteral, addList, cast…).
- Rebuild, then synchronise the database: the column is created in the entity's SQL view.
Simplified version of the method:
private static str formatNameAndAddress()
{
DataEntityName dataEntityName = tablestr(FMCustomerEntity);
List fieldList = new List(types::String);
fieldList.addEnd(SysComputedColumn::returnField(dataEntityName,
identifierstr(FMCustomer), fieldstr(FMCustomer, FirstName)));
fieldList.addEnd(SysComputedColumn::returnLiteral(" "));
fieldList.addEnd(SysComputedColumn::returnField(dataEntityName,
identifierstr(FMCustomer), fieldstr(FMCustomer, LastName)));
fieldList.addEnd(SysComputedColumn::returnLiteral("; "));
fieldList.addEnd(SysComputedColumn::returnField(dataEntityName,
identifierstr(FMAddressTable), fieldstr(FMAddressTable, City)));
return SysComputedColumn::addList(fieldList);
}Tip from Microsoft: if synchronisation fails, first work out the SQL expression in SQL Server Management Studio, then translate it into X++.
And the virtual field?
Create an Unmapped field with IsComputedField = No, then override postLoad to compute the value on read:
public void postLoad()
{
super();
// Virtual field: "LastName, FirstName"
this.FullName = this.LastName + ", " + this.FirstName;
}To accept this value on write (for example an external system sending "LastName, FirstName"), override mapEntityToDataSource and split the value into the fields of the relevant data source.
Common mistakes
- Forgetting to synchronise the database after building: the column does not exist in the view.
- Writing a join inside the SQL expression: Microsoft recommends adding the required table as a data source of the entity instead, otherwise SQL computes row by row.
- Letting the method throw an exception: synchronisation catches it, sets the column to NULL and only logs a warning. Check configuration keys inside the method.
- Using postLoad (virtual field) for simple formatting: the export goes through the staging table and slows down.
- Mixing types without a cast: use SysComputedColumn::cast for concatenated numeric or date fields.
Going further
To create the entity itself and export it, read create a data entity and export it with DMF. Skalp AI generates this kind of development (entity, computed columns, unit tests), delivered to your Azure DevOps and validated by your IT lead: see data entities and DMF packages, the bigger picture in building X++ without a consultant in 2026 and the Basic, Pro and Max plans.
Sources
- Microsoft Learn, "Computed columns and virtual fields in data entities", updated 14 Jan 2026, accessed 11 Oct 2026.
- Microsoft Learn, "Data entity export performance tips", updated 26 Sep 2026, accessed 11 Oct 2026.
Frequently asked questions
Is a computed column stored in the database?
No. It is a computed column of the entity's SQL view. On write, X++ code splits the value into the real fields of the data sources, which are stored.
Can you filter on a virtual field?
No, search and filtering are not supported on virtual fields. Use a computed column if you need to filter.
Why does my computed column return NULL?
The method generating the SQL expression probably threw an exception during synchronisation: the column is then set to NULL with only a warning. Check the synchronisation log and configuration keys.
Ready to transform your D365?
Join the CIOs who develop their D365 tickets in 1h for 1 credit (≈ €400 on Basic, €200 on Pro).