Unofficial Content
  • This documentation is valid for:

A special case of a transaction is that where only one record is allowed to exist. This kind of transaction is often used for System Parameters implementations.

The way to make sure that there aren't any more records is by defining a Surrogate Key and setting its value in the rules:

Transaction: Parameters

Structure

ParameterId* // this is the surrogate key

DefaultCurrency

ChartServer

Rules

// housekeeping to ensure only one record exists

noaccept(ParameterId);

ParameterId = 1;

error('Cannot delete parameters') if delete;

// default values

default(DefaultCurrency, DefaultCurrencyConstant.Currency); // DefaultCurrencyConstant enum domain

default(ChartServer, GeneralConstants.ChartServer); // GeneralConstants enum domain

 This transaction can be used for setting the attributes, but there are several ways to access them in code:

Using a For Each

For Each

Where ParameterId = 1 // not strictly needed, just for defensive programming

&ChartServer = ChartServer

...

When None

&ChartServer = GeneralConstants.ChartServer // the record wasn't created yet

...

Endfor

In order to define the condition in only one place, Data Selectors can be used:

For Each Using ParameterDataSelector() // where ParameterDataSelector has the ParameterId = 1 condition

&ChartServer = ChartServer

...

When None

&ChartServer = GeneralConstants.ChartServer // the record wasn't created yet

...

Endfor

The problem with this solution is that the When None logic has to be duplicated everywhere (unless there is a way to make sure that a record is always inserted). A better solution can be the one below.

Encapsulating Parameter Access in Procedures   

Procedure: GetChartServer

parm(out:&ChartServer)

for each

where ParameterId = 1

&ChartServer = ChartServer

when none

&ChartServer = GeneralConstants.ChartServer // defensive programming, just in case the parameter record wasn't inserted

endfor

This solves the problem of always having values for every attribute even if the record wasn't inserted yet (in this case default values are returned).

Using Data Provider  

ChartInfo Where ParameterId = 1

{

Server = ChartServer

Parms = FixedParms

}

ChartInfo Default //equivalent to when none in procedural

{

Server = GeneralConstants.ChartServer

Parms = GeneralConstants.FixedParms

}

Note: it's very easy to add another layer with this approach, for example, to check first for User Parameters, later for System Parameters and at last for System Constants:

ChartInfo Where UserParameterId = UserId()

{

Server = UserChartServer

Parms = UserFixedParms

}

ChartInfo Default Where ParameterId = 1

{

Server = ChartServer

Parms = FixedParms

}

ChartInfo Default //equivalent to when none in procedural

{

Server = GeneralConstants.ChartServer

Parms = GeneralConstants.FixedParms

}

Example

In gxwiki itself all system parameters were implemented using a  single One Record Transaction:

gxwiki parameters structure

gxwiki parameters rules

gxwiki parameters udp

Last update: February 2024 | © GeneXus. All rights reserved. GeneXus Powered by Globant