When upgrading an extension from C/AL to AL (version 1 to version 2) we need to think about the data upgrade process.

In C/AL we needed to add two function to an extension Codeunit to handle the installation and upgrade. This I did with Codeunit 70009200. One function to be execute once for each install.
PROCEDURE OnNavAppUpgradePerDatabase@1();
VAR
AccessControl@70009200 : Record 2000000053;
BEGIN
WITH AccessControl DO BEGIN
SETFILTER("Role ID",'%1|%2','SUPER','SECURITY');
IF FINDSET THEN REPEAT
AddUserAccess("User Security ID",PermissionSetToUserGLSourceNames);
AddUserAccess("User Security ID",PermissionSetToUpdateGLSourceNames);
AddUserAccess("User Security ID",PermissionSetToSetupGLSourceNames);
UNTIL NEXT = 0;
END;
END;
And another function to be executed once for each company in the install database.
PROCEDURE OnNavAppUpgradePerCompany@2();
VAR
GLSourceNameMgt@70009200 : Codeunit 70009201;
BEGIN
NAVAPP.RESTOREARCHIVEDATA(DATABASE::"G/L Source Name Setup");
NAVAPP.RESTOREARCHIVEDATA(DATABASE::"G/L Source Name User Setup");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"G/L Source Name");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"G/L Source Name Help Resource");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"G/L Source Name User Access");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"G/L Source Name Group Access");
GLSourceNameMgt.PopulateSourceTable;
RemoveAssistedSetup;
END;
For each database I add my permission sets to the installation users and for each company I restore the setup data for my extension and populate the lookup table for G/L Source Name.
The methods for install and upgrade have changed in AL for extensions version 2. Look at the AL documentation from Microsoft for details.
In version 2 I remove these two obsolete function from my application management Codeunit and need to add two new Codeunits, one for install and another for upgrade.
codeunit 70009207 "O4N GL Source Name Install"
{
Subtype = Install;
trigger OnRun();
begin
end;
var
PermissionSetToSetupGLSourceNames : TextConst ENU='G/L-SOURCE NAMES, S';
PermissionSetToUpdateGLSourceNames : TextConst ENU='G/L-SOURCE NAMES, E';
PermissionSetToUserGLSourceNames : TextConst ENU='G/L-SOURCE NAMES';
trigger OnInstallAppPerCompany();
var
GLSourceNameMgt : Codeunit "O4N GL SN Mgt";
begin
GLSourceNameMgt.PopulateSourceTable;
RemoveAssistedSetup;
end;
trigger OnInstallAppPerDatabase();
var
AccessControl : Record "Access Control";
begin
with AccessControl do begin
SETFILTER("Role ID",'%1|%2','SUPER','SECURITY');
if FINDSET then repeat
AddUserAccess("User Security ID",PermissionSetToUserGLSourceNames);
AddUserAccess("User Security ID",PermissionSetToUpdateGLSourceNames);
AddUserAccess("User Security ID",PermissionSetToSetupGLSourceNames);
until NEXT = 0;
end;
end;
local procedure RemoveAssistedSetup();
var
AssistedSetup : Record "Assisted Setup";
begin
with AssistedSetup do begin
SETRANGE("Page ID",PAGE::"O4N GL SN Setup Wizard");
if not ISEMPTY then
DELETEALL;
end;
end;
local procedure AddUserAccess(AssignToUser : Guid;PermissionSet : Code[20]);
var
AccessControl : Record "Access Control";
AppMgt : Codeunit "O4N GL SN App Mgt.";
AppGuid : Guid;
begin
EVALUATE(AppGuid,AppMgt.GetAppId);
with AccessControl do begin
INIT;
"User Security ID" := AssignToUser;
"App ID" := AppGuid;
Scope := Scope::Tenant;
"Role ID" := PermissionSet;
if not FIND then
INSERT(true);
end;
end;
}
In the code you can see that this Codeunit is of Subtype=Install. This code will be executed when installing this extension in a database.
To confirm this I can see that I have the G/L Source Names Permission Sets in the Access Control table .

And my G/L Source Name table also has all required entries.

Uninstalling the extension will not remove this data. Therefore you need to make sure that the install code is structured in a way that it will work even when reinstalling. Look at the examples from Microsoft to get a better understanding.
Back to my C/AL extension. When uninstalling that one the data is moved to archive tables.

Archive tables are handled with the NAVAPP.* commands. The OnNavAppUpgradePerCompany command here on top handled these archive tables when reinstalling or upgrading.
Basically, since I am keeping the same table structure I can use the same set of commands for my upgrade Codeunit.
codeunit 70009208 "O4N GL SN Upgrade"
{
Subtype=Upgrade;
trigger OnRun()
begin
end;
trigger OnCheckPreconditionsPerCompany()
begin
end;
trigger OnCheckPreconditionsPerDatabase()
begin
end;
trigger OnUpgradePerCompany()
var
GLSourceNameMgt : Codeunit "O4N GL SN Mgt";
archivedVersion : Text;
begin
archivedVersion := NAVAPP.GetArchiveVersion();
if archivedVersion = '1.0.0.1' then begin
NAVAPP.RESTOREARCHIVEDATA(DATABASE::"O4N GL SN Setup");
NAVAPP.RESTOREARCHIVEDATA(DATABASE::"O4N GL SN User Setup");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"O4N GL SN");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"O4N GL SN Help Resource");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"O4N GL SN User Access");
NAVAPP.DELETEARCHIVEDATA(DATABASE::"O4N GL SN Group Access");
GLSourceNameMgt.PopulateSourceTable;
end;
end;
trigger OnUpgradePerDatabase()
begin
end;
trigger OnValidateUpgradePerCompany()
begin
end;
trigger OnValidateUpgradePerDatabase()
begin
end;
}
So, time to test how and if this works.
I have my AL folder open in Visual Studio Code and I use the AdvaniaGIT command Build NAV Environment to get the new Docker container up and running.
Then I use Update launch.json with current branch information to update my launch.json server settings.

I like to use the NAV Container Helper from Microsoft to manually work with the container. I use a command from the AdvaniaGIT module to import the NAV Container Module.

The module uses the container name for most of the functions. The container name can be found by listing the running Docker containers or by asking for the name that match the server used in launch.json.

I need my C/AL extension inside the container so I executed
Copy-FileToNavContainer -containerName jolly_bhabha -localPath C:\NAVManagementWorkFolder\Workspace\GIT\Kappi\NAV2017\Extension1\AppPackage.navx -containerPath c:\run
Then I open PowerShell inside the container
Enter-NavContainer -containerName jolly_bhabha
Import the NAV Administration Module
Welcome to the NAV Container PowerShell prompt
[50AA0018A87F]: PS C:\run> Import-Module 'C:\Program Files\Microsoft Dynamics NAV\110\Service\NavAdminTool.ps1'
Welcome to the Server Admin Tool Shell!
[50AA0018A87F]: PS C:\run>
and I am ready to play. Install the C/AL extension
Publish-NAVApp -ServerInstance NAV -IdePath 'C:\Program Files (x86)\Microsoft Dynamics NAV\110\RoleTailored Client\finsql.exe' -Path C:\run\AppPackage.navx -SkipVerification
Now I am faced with the fact that I have opened PowerShell inside the container in my AdvaniaGIT terminal. That means that my AdvaniaGIT commands will execute inside the container, but not on the host.
The simplest way to solve this is to open another instance of Visual Studio Code. From there I can start the Web Client and complete the install and configuration of my C/AL extension.

I complete the Assisted Setup and do a round trip to G/L Entries to make sure that I have enough data in my tables to verify that the data upgrade is working.

I can verify this by looking into the SQL tables for my extension. I use PowerShell to uninstall and unpublish my C/AL extension.
Uninstall-NAVApp -ServerInstance NAV -Name "G/L Source Names"
Unpublish-NAVApp -ServerInstance NAV -Name "G/L Source Names"
I can verify that in my SQL database I now have four AppData archive tables.
Pressing F5 in Visual Studio Code will now publish and install the AL extension, even if I have the terminal open inside the container.

The extension is published but can’t be installed because I had previously installed an older version of my extension. Back in my container PowerShell I will follow the steps as described by Microsoft.
[50AA0018A87F]: PS C:\run> Sync-NAVApp -ServerInstance NAV -Name "G/L Source Names" -Version 2.0.0.0
WARNING: Cannot synchronize the extension G/L Source Names because it is already synchronized.
[50AA0018A87F]: PS C:\run> Start-NAVAppDataUpgrade -ServerInstance NAV -Name "G/L Source Names" -Version 2.0.0.0
[50AA0018A87F]: PS C:\run> Install-NAVApp -ServerInstance NAV -Tenant Default -Name "G/L Source Names"
WARNING: Cannot install extension G/L Source Names by Objects4NAV 2.0.0.0 for the tenant default because it is already installed.
[50AA0018A87F]: PS C:\run>
My AL extension is published and I have verified in my SQL server that all the data from the C/AL extension has been moved to the AL extension tables and all the archive tables have been removed.
Back in Visual Studio Code I can now use F5 to publish and install the extension again if I need to update, debug and test my extension.
Couple of more steps left that I will do shortly. Happy coding…