An optional clause in the For Each command allows us to define the Transaction (or Transaction level) that we want to use as Base Table for the For Each.
See Base Transaction clause for the general aspects.
For Each Invoice
Print CustomerName, InvoiceDate
For Each Invoice.Line
Print ProductName, InvoiceLineQuantity, InvoiceLinePrice, InvoiceLineTotal
We call the mentioned transaction (or transaction level) the Base Transaction of the For Each.
When we define the Base Transaction of the For Each, GeneXus directly infers its Base Table.
The Base Transaction also applies to Data Providers and grids. See Base Transaction in Data Providers for more details.
It is possible to reference several Base Transactions. This option eases the expression for navigations over different tables.
Sometimes you need to solve queries which imply the navigation over different tables, and are difficult to express using N For Eachs. It may also happen that without the Base Transaction clause these queries cannot be solved in a single SQL sentence.
Let's take into account the following transaction structures and code:
UserType ("Common","Administrator", etc.)
For Each User, Program
where UserType = "Administrator"
Print UserName, ProgramName
In this case, a cartesian product is done, listing all the possible combinations of users and programs (for the "administrator" user). Note that in the same line is printed the UserName and the ProgramName, for each combination.
See Multiple Base Transactions in a For Each command for more specific examples of this scenario.
How is the base table determined
If one base transaction is declared in the For Each, the table associated with that base transaction is considered as the base table, and the attributes inside the body of the For Each, conditions, orders, etc. have to be included in the extended table.
If more than one base transaction is declared, if it's possible, a JOIN is made between the tables associated to these transactions. Otherwise, a cartesian product is done. The attributes of the For Each have to be in the extended table of any of these tables.
In addition to the scenarios presented above, the advantages of using the base TRN in the For each include:
• Improved capacity to understand existing KBs. If the For Each has base TRN then a developer facing a new KB will not have to see the navigation to determine the table on which the iteration is taking place.
• Enhanced expressive capacity of the For Each and more simplicity.
• Improved specification time.
Time for the specification is improved because it isn't needed to do the calculation of the For Each’s base table.
• Reference in the KB between base TRNs and their For Each.
The KB stores the reference between the TRN and the For Eachs that use it as base TRN, so, if a TRN changes, we can directly see the For Eachs that may be affected by such change.
As of GeneXus X Evolution 3.
In order to avoid ambiguity in the For Each Order clause, the Order clause is not optional anymore.
In case you program the following, you will get an error: error: Program 'AttributeX' does not exist:
For Each AttributeX
You need to change it to:
For Each Order AttributeX
In case of KBs which are converted to GeneXus X Evolution 3, or xpz files which were generated in a previous version, an automatic conversion is performed when the object is opened or specified.