Force App Schema Changes
Microsoft recommends against making destructive schema changes, i.e. by removing fields from tables, renaming, or changing types, to name a few. But in some cases, it's necessary. This section lists the options available to sync app(s) with force.
Warning
Forcing a schema synchronization can delete data in the affected tables and fields. Only use force-sync when you understand the changes being applied and accept the potential data loss.
Always Force
You can allow force synchronize the schema on all apps by setting AllowForceSync to true in the bc-server package. This applies the force schema synchronization across all apps in the instance:
$Arguments = @{
'bc-server' = @{
AllowForceSync = 'true'
}
}
Install-UscPackage -Id 'bundle/pos' -InstanceName 'LSCentral' -Arguments $Arguments
You can also allow forcing schema changes only for specific apps by setting AllowForceSync to true for those packages:
$Arguments = @{
'ls-central-app' = @{
AllowForceSync = 'true'
}
'my-app' = @{
AllowForceSync = 'true'
}
}
Install-UscPackage -Id 'bundle/pos' -InstanceName 'LSCentral' -Arguments $Arguments
Adjust the script to list the app packages you want to force. In the example above, bundle/pos, LSCentral, ls-central-app and my-app are placeholders, replace them with your own bundle ID, instance name and package IDs.
Note
Argument values must be passed as strings, so set AllowForceSync to 'true' (with quotes), not the boolean $true.
Note
Parameter changes are only applied when packages are updated. This applies to both examples above. If you have only one app being updated that needs AllowForceSync, you must apply the parameter to the target app itself, not bc-server. Changes to bc-server's AllowForceSync will only take effect when bc-server is updated.
This method is only recommended during development and for test instances.
In production, you can be more selective and only allow force-sync for a specific version of an app where you approve forcing the schema changes. See the next section for further information.
Selective Force-Sync
If your app needs to do destructive schema changes for a particular version, you can include metadata with the app package that allows Update Service to force-sync the changes, even if the parameter AllowForceSync is set to false.
This is accomplished by including metadata with the package version that introduces the destructive changes and all versions after that.
Here are few examples of different updating scenarios and if force-sync is applied. Let's say that destructive schema changes were introduced in 2.0.0:
1.0.0 -> 1.9.0 = No force
1.9.0 -> 2.0.0 = Force
1.0.0 -> 2.1.0 = Force
2.1.0 -> 2.2.0 = No force
Force applies whenever the update path crosses the ForceVersion, including when upgrading from a version before it directly to a later one (e.g. 1.0.0 -> 2.1.0).
If your app introduces destructive schema changes in multiple versions, set ForceVersion to the latest version that introduces them, but never higher than the version being installed.
From App's Context (New-AppPackageFromContext)
When using New-AppPackageFromContext to create the app package, you can add the metadata as an argument as following:
Import-Module LsPackageTools\AppPackageCreator
$Package = @{
Path = @('c:\path\to\extension.app')
AppMetadata = @{
ForceVersion = "2.0.0"
}
Dependencies = @(
...
)
...
}
New-AppPackageFromContext @Package
AppMetadata.json
With New-AppPackage and Invoke-AlProjectBuild, create a file called AppMetadata.json with the following structure:
{
"ForceVersion": "2.0.0"
}
where you specify the version that introduces the schema changes with the ForceVersion property.
From AL Project (Invoke-AlProjectBuild)
If you are using Update Service Workspace (or Invoke-AlProjectBuild), you need to update gocurrent.json to include the AppMetadata.json file:
{
"id": "my-app",
"version": "2.0.0",
"name": "${alAppName}",
"description": "${alAppDescription}",
"files": [
"${alAppProjectDir}\\${alAppPublisher}_${alAppName}_${alAppVersion}.app",
"${alAppProjectDir}\\.gocurrent\\AppMetadata.json"
],
...
}
{
"id": "my-app",
"version": "2.0.0",
"name": "${alAppName}",
"description": "${alAppDescription}",
"files": [
"${alAppProjectDir}\\${alAppPublisher}_${alAppName}_${alAppVersion}.app",
"${alAppProjectDir}\\.gocurrent\\AppMetadata.json"
],
...
}
From App, Basic (New-AppPackage)
Using New-AppPackage, include the AppMetadata.json with the path argument, along with the app file path:
Import-Module LsPackageTools\AppPackageCreator
$Package = @{
Id = 'my-app'
Name = 'My App'
Version = '2.0.0'
Path = @('c:\path\to\extension.app', 'c:\path\to\AppMetadata.json')
Dependencies = @(
...
)
...
}
New-AppPackage @Package