MDS could auto-generate a Code. Turn it on, and every new member got the next integer in line, starting value plus increment, nothing more. Say you wanted a code or a name that meant something: a ward called KAR-3 because it is room 3 of the cardiology clinic, an order line stamped with its launch date. MDS had no rule for that. You built it in Excel before the file went anywhere near the model, or a data steward typed it by hand, row after row, and hoped nobody fat-fingered the dash.
As of 1.2026.8.27, a Primentra business rule does it for you: read the other columns of the same row, join them the way you specify, and write the result into a blank Code or Name. The ward example is not hypothetical. It is the case we tested the rule against before shipping it, because a name built wrong is worse than a name typed wrong: it looks correct on every row.
The gap in MDS was real, not a rounding error
Microsoft's own documentation for automatically generating attribute values describes exactly one mechanism: an integer, a starting value, and an amount to increment by. That is a fine tool for a purely arbitrary identifier, and MDS was honest that it was arbitrary. The whole point of that kind of Code is that it carries no meaning at all. The moment you wanted a code or name that did carry meaning, built from two or three columns of the row it belongs to, there was no rule action for it. You reached for Excel, for InfoPath customization, or you accepted that the field would be typed by hand and would eventually drift.
That drift is the part worth naming. A significant code, one where the structure means something to the person reading it, is only worth having if it is built the same way every time. The instant one steward writes KAR-3 and another writes KAR3 or Kardiologie-3, the code stops being something you can sort, filter, or join on with any confidence. Manual entry does not just risk typos. It risks three different people inventing three different conventions for the same idea.
How the rule is built
It comes from the same Fill a value template that already fills a blank column with a fixed default. Choose Built from other columns instead of a fixed value, and the form changes shape.
Pick the target
Name, Code (when not auto-generated), or any ordinary column
Add the parts, in order
A column, a piece of literal text, another column — as many as you need
Save
The rule fills the column on every row that leaves it empty, from then on
A column contributes the value the grid shows for it. A domain column contributes the code of the row it points at, not its internal ID. A date is the one exception: it reads as YYYYMMDD, with no time and no separators, so a code carrying a launch date still sorts correctly next to every other code. Name and Code are built this way exclusively. There is no fixed-value option for either, because a fixed Name defeats the point of having one.
It refuses to guess at a missing part
The obvious failure mode for a rule like this is a half-filled row. Clinic is KAR, Room has not been entered yet. What does the rule write? Not KAR-. A row only receives a built value when every column the rule reads carries something. With Room still blank, the rule writes nothing, Name stays empty, and the row is refused for a missing Name, which names the actual problem. A trailing dash would have looked like success and meant nothing.
The grid says so before you even save. A column a rule will build shows Built in place of the red Required placeholder it used to carry, and it stops asking you to type something the rule is about to supply. That sounds cosmetic until you have hit the alternative: I have seen a grid refuse a blank Name outright, before the rule building it ever got a turn to run.
Built once, not recalculated
The value is built the moment the target column is empty, and only then. Move that ward to a different Room afterward and its Name stays KAR-3. The rule does not notice and does not rebuild it. That is the same promise every filling rule in Primentra makes: it fills a blank, and it never overwrites a value that is already there, including a value it wrote itself a minute ago. Correcting a built name by hand is therefore permanent. Type over KAR-3 and the column is no longer empty, so the rule leaves it alone from then on.
That is also what separates a built value from a derived column, which looks similar on the surface but does the opposite job. A derived column is read-only and always live: move a Costcenter to a different Area and the derived Zone column updates on its own, because it is recalculated on every read. A built Code or Name is an ordinary, editable column that happens to have been filled in automatically once. Use a derived column when the value must always match its source. Use a built value when the value only needs to be right at the moment it is created.
Where it runs
A built value applies on every route that writes a row: a grid save, a paste, a file import, a staging batch, an approved change, and the REST API. Each of those had its own reason to refuse a blank Code or Name before this shipped, and each of them now asks first whether a rule supplies it. A file import that used to fail eight hundred rows for a missing Name can, if the name is derivable from other columns in the file, stop failing them at all.
Where several filling rules exist on one entity, they run in the order you arrange them, and a later rule sees what an earlier one just wrote. Build Name from Clinic and Room, then build a Search Label from Name and a Status column, and the second rule reads the Name the first one produced, not the blank that used to be there. It cannot loop back on itself: once a column is filled it is no longer blank, so there is nothing left for a rule to act on.
What it does not do
It does not check that the result is unique. A ward named KAR-3 built from Clinic and Room can still collide with a KAR-3 someone typed in by hand years ago, and the rule has no opinion about that. Pair it with a combination-unique rule on the same source columns if the combination is supposed to be one-of-a-kind. It does not rewrite anything that already exists: switching the rule on does not touch a single row already in the table, so a backfill against existing blanks is a separate, deliberate action, not a side effect of saving the rule. And it has no severity, because it cannot refuse a save the way a validation rule can. The worst it does is leave a column empty, and the missing-value check downstream is what catches that.
Common questions
How do I build a code or name from other columns?
Create a business rule from the Fill a value template, pick the target column, and choose Built from other columns. Add the parts in the order they should read — a column, a piece of text, another column. Code is only offered as a target when Auto-generate Code is off, because the generator already hands out a code before any rule could run.
What if one of the source columns is empty?
The rule writes nothing. A built value only comes out when every column it reads carries something, so a missing Room does not become KAR- with a dangling dash. The target stays blank, and a required target is refused by name — which is more useful than a value that is silently half right.
Does it update when a source column changes later?
No. It is built once, while the target is still empty. Change the source afterward and the built value stays exactly as it was. That is the same promise every filling rule makes, and it is why correcting a built name by hand is safe forever after.
Could MDS do this?
Only the sequential-integer half. MDS could auto-generate Code, or another attribute, as a starting value plus an increment. It had no rule action for reading other attributes of the same row and joining them, so a meaningful composed code or name had to be built outside MDS, usually in Excel before the import.
Stop typing codes that were always going to be inconsistent
Build the rule against your own model, in the business rules engine, and watch it fill a real row. Primentra runs on your own SQL Server, deploys in a day, and costs €7,500 per year flat, with a 60-day trial.