ZuloOne
English
Sign in
Menu

Create a link table

Updated

A link table is an M:N set of rows between records. Files live in LinkTables/ of your model. The physical table is LT_{Name}. The generated class is LT_{Name}. Kind: Link table.

Note

A link table is not a child list. If one side owns the other and cascade delete is required, use a dictionary list or a document table part.

How to#

1. The file — LinkTables/<Name>.json, kind: "LinkTable". A new GUID in metaId. modelId is your model's. Names are PascalCase Latin. tableName is LT_{Name}.

Each side is a property with isReference: true, referenceKind: "Dictionary" (or a document), and referenceMetaId of the target. Extra columns are scalars (baseType plus length / precision+scale). One fieldName once.

isPrimaryKey on a reference keeps the card tab on that side only: PriceTypeHistory hangs off the item, not the price type.

Dated intervals with a closed window (EffectiveFrom / EffectiveTo) live here — PriceTypeHistory in Inventory is the worked example. An information register is a slice: the last value continues until a later Period.

A simple M:N with no window is CountryCurrency in Common (Country, Currency, IsPrimary).

2. Use it from a script — GetService<ILinkTableManager>(). By name: AddAsync / EnsureAsync / GetAsync / DeleteAsync. Typed over the generated row class:

var links = GetService<ILinkTableManager>();

var outlets = await links.GetRecordsAsync<LT_SalesContractOutlet>(
    "SalesContract", contractId);

await links.ReplaceRecordsAsync("SalesContract", contractId, rows);

await links.SaveRecordAsync(new LT_PriceTypeHistory
{
    Item = itemId,
    PriceType = typeId,
    Unit = unitId,
    Price = price,
    EffectiveFrom = from,
});

ReplaceRecordsAsync makes that side exactly the given set: rows of (keyField = keyValue) missing from the set are deleted.

A data package can ship link-table rows (kind: LinkTable, key = the reference pair).

3. Bump modelVersion in the same change.

Warning

ReplaceRecordsAsync deletes every row of that side that you did not pass. Build the full set, then replace. EnsureAsync is the idempotent add: it returns the existing row when one already matches all the given values.

The dictionary card shows the link table whose column points at it. There is no menu item: the user opens the tab on the card.

What's not there yet#

There is no catalog card in Reference that lists every LT_ table. Look in LinkTables/ of the model. A link table is not a totals register and not a slice.

Where next#

Was this page helpful?