Microsoft Dynamics AX (now part of Dynamics 365 Finance & Operations) was and still is a multi-legal-entity (multi-company) ERP system. Go ahead and start your journey now to upgrade your knowledge on what x++ is used for in D365 FinOps modern ERP with the help of Dynamics Edge.
In Dynamics AX / Finance & Operations Data generally being partitioned by company (also called legal entity). That is meaning most of your Dynamics 365 Finance and Operations CrossCompany vs ChangeCompany X++ queries and operations are scoped to the current company context. To work with data across company boundaries, X++ (the AX/Finance & Ops programming language) provides two key constructs: crossCompany
and changeCompany
. These allow developers to access or manipulate data in other company contexts, but in different ways. Below, we explain what each does, provide real-world examples, and then compare and contrast them (including usage in AX 2009, AX 2012, and the latest Finance & Operations).
What is crossCompany
?
In X++, the crossCompany
keyword allows a select query to retrieve data from multiple companies (including the option of all companies) in a single go. When you use crossCompany
in a select statement, AX will return records from all specified company partitions without needing to manually switch context. By default, if no specific companies are listed, it will fetch records from all companies. You can also limit the scope by providing a container of company IDs, so the query only returns data from those particular legal entities. Importantly, crossCompany
is only used with read (select) operations – it cannot be used to insert or update records across companies.
Real-world scenario: Imagine a global business wants to generate a consolidated report of all customers across all its subsidiaries (legal entities). Using crossCompany
in an X++ select query, a developer can fetch customer records from every company at once, rather than running separate queries per company. This is useful for reporting or data analysis – for example, listing all vendors from all country offices to identify duplicates or global spend. In one X++ job or report query, crossCompany
can retrieve, say, every vendor from all company partitions, producing output that includes the vendor’s account and the company they belong to. This single-pass approach is efficient for read-only data aggregation across many companies.
What is changeCompany
?
The changeCompany
construct in X++ allows you to change the current execution context to a different company (legal entity) for a block of code. In practice, you call changeCompany("CompanyID")
with a target company’s identifier, and within the curly-braced block that follows, any database operations run as if the code is logged into that company. This means you can select, insert, update, or delete data in that other company’s context. Unlike crossCompany
, which is limited to queries, changeCompany
works for all data operations (CRUD). However, it operates on one company at a time – you must specify a single company each time you use it (you cannot fetch or affect multiple companies simultaneously in one changeCompany
block). To work with multiple companies, you would typically loop through a list of company IDs and call changeCompany
for each in turn.
Real-world scenario: Consider an organization that needs to perform an action in each of its companies, such as initializing settings or creating a record in all legal entities. With changeCompany
, a developer can programmatically loop through each company. For example, you could iterate through all company IDs in the system and within each iteration use changeCompany(companyId) { ... }
to, say, create a new customer or copy a configuration record in that specific company. Each iteration temporarily switches the context, performs the insert/update, then moves on. This is crucial for scenarios like intercompany operations or data synchronization: e.g. if a new product needs to be created in several companies, you can write X++ code that uses changeCompany
to create the product in company A, then company B, and so on, all in one execution. Without changeCompany
, you’d have to manually log into each company’s session or use separate service calls. Essentially, changeCompany
enables multi-company automation by handling one company at a time, including write operations that crossCompany
cannot do.
Key Differences Between crossCompany
and changeCompany
Both crossCompany
and changeCompany
let you work with data across company boundaries, but they differ in syntax, capabilities, and typical use cases. Below are the core differences:
- Syntax and Usage Context:
crossCompany
is a keyword used inline in select statements, whereaschangeCompany
is used as a block structure with curly braces encompassing X++ code. For example, you might writeselect crossCompany * from CustTable;
versus usingchangeCompany("USMF") { ... }
with a block of code. The former modifies a query, the latter changes execution context for a code segment. - Read vs. Write Operations:
crossCompany
applies only to data retrieval (SELECT). You can perform queries across multiple companies, but you cannot directly insert/update/delete usingcrossCompany
. In contrast,changeCompany
allows full CRUD operations under the target company’s context. If you need to create or modify records in another company, you must usechangeCompany
(or an equivalent context change), since cross-company write operations are not allowed otherwise. In fact, Finance & Operations will throw errors like “Insert operations are not allowed across companies” unless you switch context. Microsoft’s documentation explicitly notes that for cross-company create/update/delete, you should use thechangeCompany
keyword to change the current company context. - Scope of Companies:
crossCompany
can target multiple companies at once. By default it runs the query for all companies, or you can specify a set of companies (using a container or query ranges) to restrict it. This means one query execution can return a unified result set containing records from many legal entities. On the other hand,changeCompany
works one company at a time – you specify a single company’s ID in each call. If your goal is to iterate through several companies, you will callchangeCompany
repeatedly (e.g. in a loop) for each company. There is no built-in way to do a singlechangeCompany
on multiple companies simultaneously – you must handle them one by one. - Result Handling: When using
crossCompany
, the result of a select query is a combined dataset. For example, aselect crossCompany * from VendTable
might return vendors from all companies, and each record carries its company identifier (DataAreaId
) so you know which company it came from. In contrast, withchangeCompany
, since you execute code separately per company, you typically handle results or operations within each company’s context. If you need a combined result fromchangeCompany
loops, you have to aggregate it yourself (e.g. storing results from each iteration). Essentially,crossCompany
is better for returning a unified multi-company view, whereaschangeCompany
is used to perform actions in isolation per company (though you could accumulate results as needed). - Performance Considerations: Because
crossCompany
pulls data in one go (often translating to a SQL query with anIN
clause listing all the specified companies), it can be efficient for reading widely — but it might also retrieve a lot of data and could become heavy if many companies are involved. In scenarios where only one company’s data is needed, usingcrossCompany
is unnecessary overhead. In fact, developers observed in AX 2009 that acrossCompany
query targeting a single company still incurred the overhead of a cross-company call (SQLIN ()
) and could become a bottleneck with many companies configured. In such cases, a simplechangeCompany
loop for that one company was more straightforward and performant. Microsoft addressed one such issue in AX 2012 R2 by replacing a single-companycrossCompany
call withchangeCompany
in standard code. On the other hand, if you truly need data from dozens of companies, a singlecrossCompany
query may outperform a loop of many context switches. The best choice can depend on the volume of data and number of companies:crossCompany
yields one combined query (with filtering by company in SQL), whereaschangeCompany
might issue separate queries per company inside a loop. - Code Maintainability: Using
crossCompany
can be succinct for read-only queries across firms – one query can replace what would otherwise be several. It also integrates with query objects (you can set a query’s.allowCrossCompany(true)
and even add specific company ranges) making it convenient for reporting scenarios.changeCompany
, however, offers more fine-grained control; inside achangeCompany
block, you can execute multiple operations, business logic, and even multiple queries under that company context. It’s essentially like programmatically logging into each company and performing a sequence of actions. The code forchangeCompany
might be longer (due to looping and context management), but it is necessary when updates or complex logic per company are needed.
Real-World Scenario Comparisons
To solidify the differences, consider a couple of scenarios:
- Scenario 1: Global Data Retrieval – Suppose the CFO wants a consolidated list of all open purchase orders across all subsidiaries in an AX/Finance & Operations deployment. A developer could write an X++ query using
crossCompany
to select from the PurchaseOrder table and retrieve all open orders in one result set. The output might include a field for company, so you can see which company each order belongs to. This single job can quickly scan every company’s data and present a merged view. Attempting the same withchangeCompany
would mean iterating through each company, querying its open orders, and merging results in code. That approach is more complex and slower due to multiple context switches. Thus,crossCompany
is ideal for such read-only reporting across many legal entities. - Scenario 2: Multi-Company Operations – Now imagine an IT administrator needs to create a new fiscal calendar or enable a feature in all companies. This is a write operation that must happen within each company’s context. Using
changeCompany
in a loop is the straightforward solution: the code switches to company A, performs the creation (e.g. adds a record or updates a setting), then switches to company B and does the same, and so on. Trying to usecrossCompany
here is not even an option, because you cannot do cross-company inserts/updates directly. Similarly, for an intercompany transaction scenario (like creating a sales order in one company that triggers a purchase order in another), a developer would usechangeCompany
to create the related record in the other company’s environment during the process. This ensures each transaction is properly recorded under the correct legal entity context.
In summary, use crossCompany
when you need to read data across multiple companies in one sweep (for example, consolidated reporting or searches across companies), and use changeCompany
when you need to perform transactions or detailed processing in another company’s context (for example, creating or updating records, or any case where writes across company boundaries are required). Both have been supported since at least AX 2009 and AX 2012, and they continue to be relevant in Dynamics 365 Finance & Operations. In newer versions (Finance & Ops), the underlying principles remain the same: queries default to the current company, but crossCompany
can override that for multi-company reads, and changeCompany
is the tool for any cross-company writes or context-specific logic. By understanding these tools and their proper use cases, developers and power users can effectively handle multi-entity data scenarios in Dynamics AX/Finance and Operations.
Have a Question ?
Fill out this short form, one of our Experts will contact you soon.
Call Us Today For Your Free Consultation
Call Now