Public/Migration/Copy-DataverseData.ps1
|
function Copy-DataverseData { <# .SYNOPSIS Copies data from one Dataverse environment to another. .DESCRIPTION Performs a complete data copy from a source to target Dataverse environment. This combines export and import into a single operation: 1. Exports data from source environment to a temporary file 2. Imports data into target environment 3. Cleans up temporary file Use this for environment-to-environment data migrations. This cmdlet wraps the ppds CLI tool. .PARAMETER SourceProfile Authentication profile for the source environment. If not specified, uses the active profile. .PARAMETER SourceEnvironment Source environment - accepts URL, friendly name, unique name, or ID. Required. .PARAMETER TargetProfile Authentication profile for the target environment. Supports comma-separated values for parallel import scaling. If not specified, uses the active profile. .PARAMETER TargetEnvironment Target environment - accepts URL, friendly name, unique name, or ID. Required. .PARAMETER SchemaPath Path to the schema.xml file defining entities to migrate. .PARAMETER TempDirectory Temporary directory for intermediate data file. Default: system temp directory .PARAMETER Parallel Maximum concurrent entity exports. Default: CPU count * 2 .PARAMETER BatchSize Records per API request. Default: 5000 (Dataverse maximum) .PARAMETER BypassPlugins Bypass custom plugin execution on target: sync, async, or all. Requires prvBypassCustomBusinessLogic privilege. .PARAMETER BypassFlows Bypass Power Automate flow triggers on target. .PARAMETER ContinueOnError Continue import on individual record failures. Default: true for copy operations. .PARAMETER StripOwnerFields Strip ownership fields allowing Dataverse to assign current user. .PARAMETER SkipMissingColumns Skip columns that exist in source but not in target environment. .PARAMETER UserMappingPath Path to user mapping XML file for remapping user references. .PARAMETER PassThru Return a copy result object with statistics. .EXAMPLE Copy-DataverseData ` -SourceEnvironment "dev" ` -TargetEnvironment "test" ` -SchemaPath "./schema.xml" Copies data from dev to test environment using the active profile. .EXAMPLE Copy-DataverseData ` -SourceProfile "dev-admin" -SourceEnvironment "https://dev.crm.dynamics.com" ` -TargetProfile "test-admin" -TargetEnvironment "https://test.crm.dynamics.com" ` -SchemaPath "./schema.xml" ` -BypassPlugins all -BypassFlows Copies with specific profiles and all plugins/flows bypassed. .OUTPUTS None by default. PSCustomObject with statistics if -PassThru is specified. #> [CmdletBinding()] param( [Parameter()] [string]$SourceProfile, [Parameter(Mandatory)] [string]$SourceEnvironment, [Parameter()] [string]$TargetProfile, [Parameter(Mandatory)] [string]$TargetEnvironment, [Parameter(Mandatory)] [string]$SchemaPath, [Parameter()] [string]$TempDirectory, [Parameter()] [int]$Parallel = 0, [Parameter()] [ValidateRange(1, 5000)] [int]$BatchSize = 5000, [Parameter()] [ValidateSet('sync', 'async', 'all')] [string]$BypassPlugins, [Parameter()] [switch]$BypassFlows, [Parameter()] [switch]$ContinueOnError, [Parameter()] [switch]$StripOwnerFields, [Parameter()] [switch]$SkipMissingColumns, [Parameter()] [string]$UserMappingPath, [Parameter()] [switch]$PassThru ) # Validate schema file exists if (-not (Test-Path $SchemaPath)) { throw "Schema file not found: $SchemaPath" } # Validate user mapping file if specified if ($UserMappingPath -and -not (Test-Path $UserMappingPath)) { throw "User mapping file not found: $UserMappingPath" } # Build arguments $cliArgs = @( 'data', 'copy' '--schema', (Resolve-Path $SchemaPath).Path '--source-env', $SourceEnvironment '--target-env', $TargetEnvironment '--output-format', 'Json' ) if ($SourceProfile) { $cliArgs += '--source-profile' $cliArgs += $SourceProfile } if ($TargetProfile) { $cliArgs += '--target-profile' $cliArgs += $TargetProfile } if ($TempDirectory) { $cliArgs += '--temp-dir' $cliArgs += $TempDirectory } if ($Parallel -gt 0) { $cliArgs += '--parallel' $cliArgs += $Parallel } if ($BatchSize -ne 5000) { $cliArgs += '--batch-size' $cliArgs += $BatchSize } if ($BypassPlugins) { $cliArgs += '--bypass-plugins' $cliArgs += $BypassPlugins } if ($BypassFlows) { $cliArgs += '--bypass-flows' } if ($ContinueOnError) { $cliArgs += '--continue-on-error' } if ($StripOwnerFields) { $cliArgs += '--strip-owner-fields' } if ($SkipMissingColumns) { $cliArgs += '--skip-missing-columns' } if ($UserMappingPath) { $cliArgs += '--user-mapping' $cliArgs += (Resolve-Path $UserMappingPath).Path } $result = Invoke-PpdsMigration -Arguments $cliArgs if ($PassThru) { return $result } } |