Public/Update-SqlConnections.ps1
function Update-SqlConnections { <# .SYNOPSIS Updates SQL connection strings in TMDL files within a Fabric semantic model. .DESCRIPTION The Update-SqlConnections function processes TMDL files in a Fabric semantic model, replacing old datawarehouse URLs and lakehouse names with new values in SQL connection strings. This is particularly useful when migrating Fabric semantic models between environments or when datawarehouse or lakehouse names have changed. .PARAMETER FolderPath The path to the folder containing the Fabric semantic model (PBISM files). The function will process TMDL files in the "definition/tables" subfolder. .PARAMETER OldDatawarehouseUrl The original datawarehouse URL to be replaced in connection strings. .PARAMETER NewDatawarehouseUrl The new datawarehouse URL to replace the old one. .PARAMETER OldLakehouseName The original lakehouse name to be replaced in connection strings. .PARAMETER NewLakehouseName The new lakehouse name to replace the old one. .PARAMETER Files Optional. Array of specific file names to process. If omitted, all TMDL files will be processed. File extensions (.tmdl) will be appended automatically if not provided. .PARAMETER ErrorOnMissingFiles Optional. When specified, the function will throw an error if any files specified in the Files parameter cannot be found. .PARAMETER WhatIf Optional. When specified, the function will report what files would be modified without actually making any changes. .EXAMPLE Update-SqlConnections -FolderPath "C:\Models\SalesModel" ` -OldDatawarehouseUrl "workspace://dw.fabric.microsoft.com/dev" ` -NewDatawarehouseUrl "workspace://dw.fabric.microsoft.com/prod" ` -OldLakehouseName "dev-lakehouse" ` -NewLakehouseName "prod-lakehouse" Updates all TMDL files in the SalesModel, replacing the dev datawarehouse URL and lakehouse name with prod values. .EXAMPLE Update-SqlConnections -FolderPath "C:\Models\SalesModel" ` -OldDatawarehouseUrl "workspace://dw.fabric.microsoft.com/dev" ` -NewDatawarehouseUrl "workspace://dw.fabric.microsoft.com/prod" ` -OldLakehouseName "dev-lakehouse" ` -NewLakehouseName "prod-lakehouse" ` -Files "Sales", "Product" ` -WhatIf Shows what changes would be made to only the Sales.tmdl and Product.tmdl files without actually changing them. .NOTES The function specifically targets string replacements in TMDL files, which contain connection information for Fabric semantic models. It ignores DateTableTemplate files and processes only valid TMDL files. When replacing lakehouse names, the function is careful to only replace names that appear within quotation marks to avoid unintended replacements. #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$FolderPath, [Parameter(Mandatory=$true)] [string]$OldDatawarehouseUrl, [Parameter(Mandatory=$true)] [string]$NewDatawarehouseUrl, [Parameter(Mandatory=$true)] [string]$OldLakehouseName, [Parameter(Mandatory=$true)] [string]$NewLakehouseName, [Parameter(Mandatory=$false)] [string[]]$Files = @("*"), [Parameter(Mandatory=$false)] [switch]$ErrorOnMissingFiles, [Parameter(Mandatory=$false)] [switch]$WhatIf ) $itemsInFolder = Get-ChildItem -LiteralPath $FolderPath -Depth 1 | Where-Object { @(".pbism") -contains $_.Extension } if ($itemsInFolder.Count -eq 0) { Write-Error "Cannot find valid item definitions ( *.pbism) in the '$FolderPath'" return } $FolderPath = Join-Path -Path $FolderPath -ChildPath "definition/tables" # Append .tmdl to each file name in $Files if it's not "*" and doesn't already end with .tmdl if ($Files -and $Files -ne @("*")) { $Files = $Files | ForEach-Object { if ($_ -ne "*" -and -not ($_ -like "*.tmdl")) { "$($_).tmdl" } else { $_ } } } # Find all TMDL files in the specified folder and subfolders $allFiles = Get-ChildItem -Path $FolderPath -Filter "*.tmdl" -Recurse | Where-Object { ($_.Name -notmatch "^(DateTableTemplate_|LocalDateTable_)") } # Filter files based on the Files parameter if ($Files -and $Files -ne @("*")) { $foundFiles = $allFiles | Where-Object { $Files -contains $_.Name } # Check if all specified files were found if ($ErrorOnMissingFiles -and $foundFiles.Count -lt $Files.Count) { $foundFileNames = $foundFiles | ForEach-Object { $_.Name } $missingFiles = $Files | Where-Object { $_ -ne "*" -and $foundFileNames -notcontains $_ } if ($missingFiles) { Write-Error "The following files were not found: $($missingFiles -join ', ')" return } } if (-not $foundFiles) { Write-Warning "No matching files found with the specified names" return } $files = $foundFiles } else { $files = $allFiles } Write-Host "Found $($files.Count) files to process" -ForegroundColor Cyan foreach ($file in $files) { Write-Host $file $content = Get-Content -Path $file -Raw # Check if the file contains the strings we're looking for if ($content -match [regex]::Escape($OldDatawarehouseUrl) -or $content -match [regex]::Escape($OldLakehouseName)) { Write-Host "Processing file: $($file)" -ForegroundColor Yellow # Replace the datawarehouse URL $updatedContent = $content -replace [regex]::Escape($OldDatawarehouseUrl), $NewDatawarehouseUrl # Replace the lakehouse name - being careful to only replace it in connection strings $pattern = "(`"|')$([regex]::Escape($OldLakehouseName))(`"|')" $replacement = "`$1$NewLakehouseName`$2" $updatedContent = $updatedContent -replace $pattern, $replacement # Check if content was modified if ($content -ne $updatedContent) { if ($WhatIf) { Write-Host " Would update: $($file)" -ForegroundColor Cyan } else { Set-Content -Path $file -Value $updatedContent -NoNewline Write-Host " Updated: $($file)" -ForegroundColor Green } } } } } |