This article gives recommendations regarding automatically generated identifiers, possible related behaviors, and what to take into account.
It is very common that you choose to use automatically generated identifiers for your Transaction objects keys in order to solve enumeration problems.
In GeneXus, this can be performed by using features such as:
To avoid synchronization conflicts, use GUID data type (with the Autogenerate Guid property set to True). In that case, a unique identifier is generated when the record is created in the device, and that identifier remains unchanged when synchronizing.
If for some reason this is not possible, several conflicts may occur, and the same for the related foreign keys.
GeneXus solves part of this problem automatically. The rest of the document briefly explains how GeneXus addresses this kind of problem and what needs to be taken into account if you use automatically generated identifiers (not autogenerated GUID).
For instance: An offline application about the classical Country-City example, where both CountryID and CityID have the Autonumber property set to True.
This app is going to be installed on two devices, and there is also a server part to accumulate all the data.
Server: has no registers
DeviceA:
CountryID |
CountryName |
1 |
Uruguay |
2 |
Brasil |
CityID
|
CityName |
CountryID |
1 |
Porto Alegre |
2 |
2 |
Montevideo |
1 |
DeviceB:
CountryID |
CountryName |
1 |
Argentina |
2 |
Paraguay |
CityID
|
CityName |
CountryID |
1 |
Buenos Aires |
1 |
2 |
Asunción |
2 |
Moment 1
The DeviceB will sync with the server and send its data. Then the server and the DeviceB will be synched.
After that, the DeviceA does the same. Which Id the DeviceA items will have?
Locally, the CountryIDs were 1 and 2. But on the server, there's already a 1 and 2 ID for Country.
The solution is to enumerate on the server on its own. So the result of both synchronizations of Country will be:
CountryID |
CountryName |
1 |
Argentina |
2 |
Paraguay |
3 |
Uruguay |
4 |
Brasil |
But what happens when CountryID is being used as a foreign key? Like in City table in this example?
Cascade updates have to be done to the subordinated tables as shown in the following table:
CityID |
CityName |
CountryID |
1 |
Buenos Aires |
1 |
2 |
Asunción |
2 |
3 |
Porto Alegre |
4 |
4 |
Montevideo |
3 |
Note: CityIDs corresponding to Porto Alegre and Montevideo were modified the same way that CountryIDs of Uruguay and Brasil.
This problem seems simple on a basic example like this one, but on bigger systems, it is much more complicated.
There is a key problem that is not solved: Variables in memory are not renamed.
That means that the following may happen:
- Record with ID = 1 is created in the device
- While some process occurs, data is synchronized and ID changed to value 2
- A variable with the ID still has value 1 in memory
- That variable is used to filter data. Problem: It filters the record with value 1, which may not exist or at least for sure is not the one expected.
This is why you should use GUID Data Type (with Autogenerate).
How does this synchronization key mapping work?
To learn more about this problem, check out the following video: Marcos Crispino´s session at the Genexus 23th event.
As from GeneXus X Evolution 3.
The Data Synchronization Problem