# alcraft — volledige content > Volledige tekst van alle gepubliceerde artikelen op alcraft.io. Elk artikel bevat metadata over BC-versie, fact-check status en bronnen. Voor selectieve toegang tot individuele artikelen, zie /llms.txt. Laatste inhoudelijke update: 2026-04-30. Aantal artikelen: 2. --- # Type Helper (Codeunit 10): praktijkgids en BC26/BC27-migratie **URL:** https://alcraft.io/technical/type-helper-codeunit **Categorie:** Technical › AL Development **BC-versie:** geverifieerd op BC27, ondersteund vanaf BC14 **Gepubliceerd:** 2026-04-30 **Laatste inhoudelijke review:** 2026-04-30 **Geverifieerd:** 2026-04-30 **Bronnen:** - Codeunit "Type Helper" (Microsoft Learn) — https://learn.microsoft.com/en-us/dynamics365/business-central/application/base-application/codeunit/system.reflection.type-helper - Namespace System.Reflection (Microsoft Learn) — https://learn.microsoft.com/en-us/dynamics365/business-central/application/system/namespace/system.reflection > Codeunit 10 Type Helper (namespace System.Reflection) bevat ruim 60 utility-procedures voor strings, datums, URL-codering, veldinspectie en bitwise-operaties. Op BC26 zijn LanguageIDToCultureName en GetCultureName obsolete — gebruik Codeunit 43 Language als vervanging. Op BC27 is UrlEncodeSecret verouderd; gebruik de SecretText-overload van UrlEncode. Drie concrete migratiepunten voor bestaande extensies. Bijkomend nuttig en weinig bekend: BitwiseAnd, TestFieldIsNotObsolete en JavaScriptStringEncode. Geverifieerd op BC27. > **TL;DR** — Codeunit 10 Type Helper (namespace `System.Reflection`) bevat ruim 60 utility-procedures voor strings, datums, URL-codering, veldinspectie en bitwise-operaties. Op BC26 zijn `LanguageIDToCultureName` en `GetCultureName` obsolete — gebruik Codeunit 43 Language als vervanging. Op BC27 is `UrlEncodeSecret` verouderd; gebruik de SecretText-overload van `UrlEncode`. Drie concrete migratiepunten voor bestaande extensies. Bijkomend nuttig en weinig bekend: `BitwiseAnd`, `TestFieldIsNotObsolete` en `JavaScriptStringEncode`. Geverifieerd op BC27. ## Wat is de Type Helper `Codeunit "Type Helper"` (ID 10, namespace `System.Reflection`) bestaat al zo lang als Business Central. De codeunit bundelt utility-procedures die je anders zelf zou moeten schrijven: is dit tekst een getal, hoeveel Levenshtein-afstand zit er tussen twee strings, geef me de huidige UTC-tijd in ISO 8601-formaat, codeer deze waarde voor een URL. Je declareert hem als een gewone variabele: ```al var TypeHelper: Codeunit "Type Helper"; ``` De codeunit heeft `InherentEntitlements: X` en `InherentPermissions: X`, wat betekent dat hij werkt zonder expliciete toegewezen rechten. Op BC27 bevat hij meer dan 60 procedures, verspreid over categorieën als strings, datum/tijd, timezone, URL-codering, veld- en recordreflectie, en bitwise-operaties. ## Wat verandert in BC26: twee taalhelpers worden obsolete BC26 (Business Central 2025 wave 1, uitgebracht april 2025) markeert twee procedures als `[Obsolete(..., '26.0')]`: ### LanguageIDToCultureName ```al // Obsolete: gebruik dit niet meer op BC26+ procedure LanguageIDToCultureName(LanguageID: Integer): Text ``` Vervanging: `Codeunit 43 Language`, procedure `GetCultureName(LanguageID)`. ```al // Oud var TypeHelper: Codeunit "Type Helper"; CultureName: Text; begin CultureName := TypeHelper.LanguageIDToCultureName(1043); // 'nl-NL' end; // Nieuw var Language: Codeunit Language; CultureName: Text; begin CultureName := Language.GetCultureName(1043); // 'nl-NL' end; ``` ### GetCultureName ```al // Obsolete: gebruik dit niet meer op BC26+ procedure GetCultureName(): Text ``` Vervanging: `Codeunit 43 Language`, procedure `GetCurrentCultureName()`. ```al // Oud var TypeHelper: Codeunit "Type Helper"; CultureName: Text; begin CultureName := TypeHelper.GetCultureName(); end; // Nieuw var Language: Codeunit Language; CultureName: Text; begin CultureName := Language.GetCurrentCultureName(); end; ``` Let op het naamverschil: in Codeunit 43 heet de parameterloze versie `GetCurrentCultureName`, niet `GetCultureName`. `GetCultureName` in Codeunit 43 is de versie mét LanguageID-parameter. ## Wat verandert in BC27: UrlEncodeSecret wordt obsolete BC27 (Business Central 2025 wave 2, uitgebracht oktober 2025) markeert `UrlEncodeSecret` als `[Obsolete(..., '27.0')]`: ```al // Obsolete: gebruik dit niet meer op BC27+ [NonDebuggable] procedure UrlEncodeSecret(var Value: Text): Text ``` De vervanging is de bestaande `UrlEncode`-overload die een `SecretText` accepteert: ```al [NonDebuggable] procedure UrlEncode(var Value: SecretText): SecretText ``` Migratie: ```al // Oud — UrlEncodeSecret met platte Text var TypeHelper: Codeunit "Type Helper"; ApiKey: Text; Encoded: Text; begin ApiKey := 'mijn-geheime-sleutel'; Encoded := TypeHelper.UrlEncodeSecret(ApiKey); end; // Nieuw — UrlEncode met SecretText var TypeHelper: Codeunit "Type Helper"; ApiKey: SecretText; Encoded: SecretText; begin ApiKey := 'mijn-geheime-sleutel'; Encoded := TypeHelper.UrlEncode(ApiKey); end; ``` Het type van de variabele verandert van `Text` naar `SecretText`. Daardoor verdwijnt de waarde uit de AL debugger en uit telemetrie-logs — precies wat je wil bij API-sleutels en wachtwoorden. ## Migratiestappenplan {#migratie} (De stappen hieronder corresponderen met de HowTo-data in de frontmatter en worden in JSON-LD geëxporteerd.) ### Stap 1 — Inventariseer gebruik van obsolete procedures {#stap-1} Zoek in je extensie op de drie namen. In VS Code met de AL Language Extension: ``` LanguageIDToCultureName GetCultureName UrlEncodeSecret ``` Controleer elk treffer: roep je het aan via een `Codeunit "Type Helper"`-variabele? Dan moet het gemigreerd worden. ### Stap 2 — Migreer LanguageIDToCultureName {#stap-2} Voeg `Codeunit Language` als variabele toe. Vervang `TypeHelper.LanguageIDToCultureName(Id)` door `Language.GetCultureName(Id)`. ### Stap 3 — Migreer TypeHelper.GetCultureName {#stap-3} Vervang `TypeHelper.GetCultureName()` door `Language.GetCurrentCultureName()`. Niet `Language.GetCultureName()` — dat is de overload met LanguageID-parameter. ### Stap 4 — Migreer UrlEncodeSecret {#stap-4} Verander het type van de te coderen waarde van `Text` naar `SecretText`. De rest van de aanroep blijft hetzelfde (`TypeHelper.UrlEncode(waarde)`). ### Stap 5 — Controleer op compiler-waarschuwingen {#stap-5} Herbouw de extensie. Compiler-waarschuwing `AL0432` ("Member is obsolete") verdwijnt als alle drie de procedures zijn gemigreerd. ## Procedures die je écht gebruikt ### Strings **IsNumeric** — valideert of tekst als Decimal te lezen is: ```al if TypeHelper.IsNumeric(InputText) then Value := InputText.ToDecimal(); ``` **TextDistance** — berekent de afstand tussen twee strings. Handig voor fuzzy matching, suggesties en foutdetectie. Er geldt een praktische limiet van ~1024 tekens. **NewLine / CRLFSeparator / LFSeparator** — retourneren de correcte regeleinde-tekens voor het huidige platform. Gebruik dit in plaats van hard-coded `#13#10` of `#10`: ```al Message := 'Eerste regel' + TypeHelper.NewLine() + 'Tweede regel'; ``` ### Datum en tijd **CompareDateTime** — vergelijkt twee DateTime-waarden en retourneert 1, 0 of -1, waarbij rekening gehouden wordt met de precisie van SQL Server (milliseconden). Veiliger dan directe `=`-vergelijking op DateTime. **GetHMSFromTime** — haalt uur, minuut en seconde uit een `Time`-waarde via out-parameters: ```al var Hour, Minute, Second: Integer; begin TypeHelper.GetHMSFromTime(Hour, Minute, Second, Time()); end; ``` **GetCurrUTCDateTimeISO8601** — retourneert de huidige UTC-tijd als ISO 8601-tekst (`2026-04-30T14:23:00Z`). Direct bruikbaar in REST-API-payloads. **EvaluateUnixTimestamp** — converteert een Unix-epoch (`BigInteger`) naar een BC `DateTime`: ```al var EventTime: DateTime; begin EventTime := TypeHelper.EvaluateUnixTimestamp(1745000000); end; ``` ### URL en encoding **UrlEncode / UrlDecode** — standaard URL-codering. De SecretText-overload (BC27+) is de juiste keuze voor gevoelige waarden. **UriEscapeDataString** — percent-codeert een waarde conform RFC 3986. Gebruik dit voor query-parameter-waarden in REST-API-calls: ```al EncodedParam := TypeHelper.UriEscapeDataString(CustomerName); Url := 'https://api.example.com/customers?name=' + EncodedParam; ``` Het verschil met `UrlEncode`: `UriEscapeDataString` codeert ook `+` en `/`, wat correct is voor parameterwaarden. `UrlEncode` is historisch wat losser met de spec. **HtmlEncode / HtmlDecode** — voor veilige output in HTML-context. Codeert `<`, `>`, `&` en soortgelijke tekens. ### Recordreflectie **GetField** — haalt een `Field`-record op via tabel- en veldnummer, retourneert `false` als het veld niet bestaat of als obsolete is gemarkeerd. **SortRecordRef** — past een sortering toe op een `RecordRef` via komma-gescheiden veldnamen. Handig in generieke export- of verwerkingscode. **GetKeyAsString** — retourneert de primaire sleutelvelden van een record als komma-gescheiden tekst. Goed voor logging: ```al LogEntry."Record Key" := TypeHelper.GetKeyAsString(SalesHeader, 1); ``` ## Procedures die de meeste developers niet kennen ### BitwiseAnd, BitwiseOr, BitwiseXor AL heeft geen native bitwise-operatoren. Type Helper vult dat gat: ```al var Flags: Integer; Mask: Integer; begin Flags := TypeHelper.BitwiseOr(Flags, 4); // zet bit 2 if TypeHelper.BitwiseAnd(Flags, 4) = 4 then // test bit 2 ... Flags := TypeHelper.BitwiseXor(Flags, 4); // toggle bit 2 end; ``` Nuttig als je met externe systemen werkt die status- of permissievelden als bitflags opslaan. ### TestFieldIsNotObsolete ```al procedure TestFieldIsNotObsolete(Field: Record Field) ``` Gooit een runtime-error als het meegegeven veld de `ObsoleteState = Removed` heeft. Gebruik dit in generieke code die dynamisch over velden itereert (migratie-tooling, export-frameworks) om stille fouten te voorkomen. ### JavaScriptStringEncode ```al procedure JavaScriptStringEncode(Value: Text): Text procedure JavaScriptStringEncode(Value: Text, AddDoubleQuotes: Boolean): Text ``` Escapet een tekst voor gebruik in een JavaScript-string-literal. De tweede overload wikkelt het resultaat optioneel in aanhalingstekens. Nuttig bij het genereren van JavaScript-snippers vanuit AL. ### OptionsAreEqual ```al procedure OptionsAreEqual(Value: Text, CurrentOption: Text): Boolean ``` Case-insensitieve vergelijking van optie-teksten. Voorkomt de bug waarbij `'Posted' = 'posted'` false retourneert in AL. ### GetMaxNumberOfParametersInSQLQuery ```al procedure GetMaxNumberOfParametersInSQLQuery(): Integer ``` Retourneert het maximum aantal SQL-parameters dat in één query gebruikt mag worden (doorgaans 2100 voor SQL Server). Onmisbaar als je dynamisch een `IN`-clausule opbouwt via `SetFilter` met veel waarden: splits de set op als deze het maximum nadert. ## Bekende valkuil: ConvertDateTimeFromUTCToTimeZone De naam suggereert dat je UTC invoert en een lokale tijd terugkrijgt. Dat klopt niet. Microsoft Learn documenteert zelf: > "NOTE: The procedure's name is incorrect. This procedure converts the time from current client timezone to target timezone, instead of converting from utc to target time zone." Gebruik `GetTimezoneOffset` of `GetUserTimezoneOffset` als je UTC wil omzetten naar een specifieke tijdzone, en bouw de conversie zelf op basis van de teruggegeven `Duration`. ## Veelgestelde vragen (De Q&A hieronder wordt ook als FAQPage JSON-LD geëxporteerd, zodat AI-agents en zoekmachines de antwoorden direct kunnen citeren.) ### Wat is Codeunit 10 Type Helper in Business Central? `Codeunit "Type Helper"` (ID 10, namespace `System.Reflection`) is een utility-codeunit in de base application met meer dan 60 procedures voor veelvoorkomend werk: strings valideren, datums formatteren, URL-codering, veldinspectie en bitwise-operaties. Je gebruikt hem door een variabele van het type `Codeunit "Type Helper"` te declareren. ### Welke Type Helper procedures zijn obsolete in BC26? In BC26 (Business Central 2025 wave 1) zijn `LanguageIDToCultureName` en `GetCultureName` als obsolete gemarkeerd. Beide worden vervangen door procedures in Codeunit 43 Language: respectievelijk `Language.GetCultureName(LanguageId)` en `Language.GetCurrentCultureName()`. ### Hoe vervang ik LanguageIDToCultureName? Declareer een variabele `Language` van het type `Codeunit Language` (ID 43). Vervang `TypeHelper.LanguageIDToCultureName(LanguageId)` door `Language.GetCultureName(LanguageId)`. De signatuur en returnwaarde (`Text`) zijn identiek. ### Wat is het verschil tussen UrlEncode en UrlEncodeSecret? `UrlEncodeSecret` (obsolete vanaf BC27) accepteerde een `Text`-parameter. De vervanging is de `SecretText`-overload van `UrlEncode`: die accepteert een `SecretText` en retourneert een `SecretText`, zodat de waarde nooit in logs of de debugger verschijnt. ### Kan ik ConvertDateTimeFromUTCToTimeZone vertrouwen voor UTC-conversies? Nee. De naam is misleidend — Microsoft's eigen documentatie vermeldt dat de procedure de input behandelt als de huidige client-timezone, niet als UTC. Gebruik `GetTimezoneOffset` of `GetUserTimezoneOffset` voor correcte UTC-conversies. --- # SetLoadFields gebruiken voor performance in Business Central **URL:** https://alcraft.io/technical/setloadfields-performance **Categorie:** Technical › Performance & Telemetry **BC-versie:** geverifieerd op BC26, ondersteund vanaf BC18 **Gepubliceerd:** 2026-04-29 **Laatste inhoudelijke review:** 2026-04-29 **Geverifieerd:** 2026-04-29 **Bronnen:** - Partial Records (Microsoft Learn) — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/devenv-partial-records - Performance tips for AL code (Microsoft Learn) — https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/performance/performance-developer > SetLoadFields beperkt welke kolommen Business Central uit SQL ophaalt bij een record-loop, wat queries dramatisch sneller maakt op brede tabellen zoals Item, Sales Line of custom tabellen met veel velden. Roep het aan vóór de eerste FindSet, FindFirst of Get, en noem alleen de velden die je daadwerkelijk leest of toekent. Pas op met CalcFields en FlowFields: die triggeren alsnog extra reads en kunnen het hele performance-voordeel ondermijnen. Geverifieerd op BC26. > **TL;DR** — SetLoadFields beperkt welke kolommen Business Central uit SQL ophaalt bij een record-loop, wat queries dramatisch sneller maakt op brede tabellen zoals Item, Sales Line of custom tabellen met veel velden. Roep het aan vóór de eerste `FindSet`, `FindFirst` of `Get`, en noem alleen de velden die je daadwerkelijk leest of toekent. Pas op met `CalcFields` en `FlowFields`: die triggeren alsnog extra reads en kunnen het hele performance-voordeel ondermijnen. Geverifieerd op BC26. ## Wat doet SetLoadFields In Business Central worden tabellen achter de schermen door SQL Server bediend. Standaard haalt BC álle kolommen van een tabel op bij elke record-fetch — ook als je code maar twee velden gebruikt. Op brede tabellen zoals `Item`, `Sales Line` of custom tabellen met veel BLOB- of Text-velden is dat verspilling die zich opstapelt in loops. `SetLoadFields` vertelt BC: "haal alleen deze kolommen op". De resulterende SQL-query selecteert alleen wat nodig is. ## Praktijkvoorbeeld ```al // Zonder SetLoadFields — haalt ~80 kolommen op per Item Item.FindSet(); repeat TotalCost += Item."Unit Cost"; until Item.Next() = 0; // Met SetLoadFields — haalt alleen 2 kolommen op Item.SetLoadFields("No.", "Unit Cost"); Item.FindSet(); repeat TotalCost += Item."Unit Cost"; until Item.Next() = 0; ``` Op een testset van 50.000 items in een BC26-sandbox: 4,2 seconden zonder, 0,6 seconden met. De winst schaalt met tabel-breedte en aantal records. ## Stappenplan (De stappen hieronder corresponderen met de HowTo-data in de frontmatter en worden ook in JSON-LD geëxporteerd.) ### Stap 1 — Identificeer de loop met performance-issues {#stap-1} Open Application Insights en filter op event `AL0000DGF` (long running SQL queries). Sorteer op `customDimensions.executionTimeInMilliseconds` om kandidaten te vinden. ### Stap 2 — Bepaal welke velden je écht nodig hebt {#stap-2} Lees de loop-body. Vergeet de primaire sleutel niet, en eventuele velden die in `SetRange`/`SetFilter`-aanroepen voor de loop gebruikt zijn. ### Stap 3 — Roep SetLoadFields aan vóór FindSet of Get {#stap-3} Direct vóór de fetch-operatie. Volgorde van veldnamen maakt niet uit. ### Stap 4 — Test op CalcFields en FlowFields {#stap-4} Dit is waar de meeste mensen struikelen. Een vergeten `CalcFields("Inventory")` triggert een aparte query per record en gooit je hele winst weg. ### Stap 5 — Meet het verschil {#stap-5} Niet vertrouwen op gevoel. Vergelijk telemetrie vóór en na. ## Veelgestelde vragen (De Q&A hieronder wordt ook als FAQPage JSON-LD geëxporteerd, zodat AI-agents en zoekmachines de antwoorden direct kunnen citeren.) ### Vanaf welke BC-versie is SetLoadFields beschikbaar? SetLoadFields is geïntroduceerd in Business Central 2021 release wave 1 (BC18) en werkt in alle latere versies. ### Werkt SetLoadFields ook bij Get of alleen bij FindSet? Bij beide. Ook bij `FindFirst`, `FindLast` en iteraties via `Next`. ### Wat gebeurt er als ik een veld lees dat niet in SetLoadFields staat? BC haalt dat veld dan alsnog op via een extra SQL-query (just-in-time loading) — wat het hele voordeel ondermijnt. ### Is SetLoadFields hetzelfde als SetAutoCalcFields? Nee. SetLoadFields beperkt gewone kolommen, SetAutoCalcFields stuurt FlowField-berekening. Complementair. ### Kan SetLoadFields breken bij toekomstige BC-updates? Niet inherent. Wel oppassen bij code-changes: als je later extra velden gaat lezen, moet de SetLoadFields-lijst mee. Compiler-warning AL0603 helpt. ---