Distribuzione database SQL di Azure

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

È possibile distribuire automaticamente gli aggiornamenti del database nel database SQL di Azure dopo ogni compilazione completata.

DACPAC

Il modo più semplice per distribuire un database consiste nel creare un pacchetto livello dati o un pacchetto DACPAC. I DACPAC possono essere usati per creare pacchetti e distribuire modifiche e dati dello schema. È possibile creare un pacchetto di applicazione livello dati usando il progetto di database SQL in Visual Studio.

Per distribuire un pacchetto di applicazione livello dati in un database SQL di Azure, aggiungere il frammento di codice seguente al file azure-pipelines.yml.

- task: SqlAzureDacpacDeployment@1
  displayName: Execute Azure SQL : DacpacTask
  inputs:
    azureSubscription: '<Azure service connection>'
    ServerName: '<Database server name>'
    DatabaseName: '<Database name>'
    SqlUsername: '<SQL user name>'
    SqlPassword: '<SQL user password>'
    DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'

Vedere anche informazioni sull'autenticazione quando si usa l'attività di distribuzione database SQL di Azure.

Script SQL

Anziché usare un pacchetto di applicazione livello dati, è anche possibile usare script SQL per distribuire il database. Di seguito è riportato un semplice esempio di script SQL che crea un database vuoto.

  USE [main]
  GO
  IF NOT EXISTS (SELECT name FROM main.sys.databases WHERE name = N'DatabaseExample')
  CREATE DATABASE [DatabaseExample]
  GO

Per eseguire script SQL come parte di una pipeline, sono necessari script di Azure PowerShell per creare e rimuovere regole del firewall in Azure. Senza le regole del firewall, l'agente di Azure Pipelines non può comunicare con database SQL di Azure.

Lo script di PowerShell seguente crea regole del firewall. È possibile archiviare questo script come SetAzureFirewallRule.ps1 nel repository.

ARM

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)
$agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroupName -ServerName $ServerName -FirewallRuleName $FirewallRuleName -StartIPAddress $agentIp -EndIPAddress $agentIP

Classico

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)

$ErrorActionPreference = 'Stop'

function New-AzureSQLServerFirewallRule {
  $agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
  New-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -RuleName $FirewallRuleName -ServerName $ServerName
}

function Update-AzureSQLServerFirewallRule{
  $agentIP= (New-Object net.webclient).downloadstring("https://api.ipify.org")
  Set-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -RuleName $FirewallRuleName -ServerName $ServerName
}

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue) -eq $null)
{
  New-AzureSQLServerFirewallRule
}
else
{
  Update-AzureSQLServerFirewallRule
}

Lo script di PowerShell seguente rimuove le regole del firewall. È possibile archiviare questo script come RemoveAzureFirewallRule.ps1 nel repository.

ARM

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)
Remove-AzSqlServerFirewallRule -ServerName $ServerName -FirewallRuleName $FirewallRuleName -ResourceGroupName $ResourceGroupName

Classico

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)

$ErrorActionPreference = 'Stop'

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue))
{
  Remove-AzureSqlDatabaseServerFirewallRule -RuleName $FirewallRuleName -ServerName $ServerName
}

Aggiungere quanto segue al file azure-pipelines.yml per eseguire uno script SQL.

variables:
  AzureSubscription: '<SERVICE_CONNECTION_NAME>'
  ResourceGroupName: '<RESOURCE_GROUP_NAME>'
  ServerName: '<DATABASE_SERVER_NAME>'
  ServerFqdn: '<DATABASE_FQDN>'
  DatabaseName: '<DATABASE_NAME>'
  AdminUser: '<DATABASE_USERNAME>'
  AdminPassword: '<DATABASE_PASSWORD>'
  SQLFile: '<LOCATION_OF_SQL_FILE_IN_$(Build.SourcesDirectory)>'

steps:
- task: AzurePowerShell@5
  displayName: 'Azure PowerShell script'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    ScriptPath: '$(Build.SourcesDirectory)\scripts\SetAzureFirewallRule.ps1'
    ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
    azurePowerShellVersion: LatestVersion

- task: CmdLine@2
  displayName: Run Sqlcmd
  inputs:
    filename: sqlcmd
    arguments: '-S $(ServerFqdn) -U $(AdminUser) -P $(AdminPassword) -d $(DatabaseName) -i $(SQLFile)'

- task: AzurePowerShell@5
  displayName: 'Azure PowerShell script'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    ScriptPath: '$(Build.SourcesDirectory)\scripts\RemoveAzureFirewallRule.ps1'
    ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
    azurePowerShellVersion: LatestVersion

Connessione al servizio di Azure

L'attività di distribuzione database SQL di Azure è il meccanismo principale per distribuire un database in Azure. Questa attività, come con altre attività di Azure predefinite, richiede una connessione al servizio di Azure come input. La connessione al servizio di Azure archivia le credenziali per connettersi da Azure Pipelines ad Azure.

Il modo più semplice per iniziare a usare questa attività consiste nell'accedere come utente proprietario sia dell'organizzazione Di Azure DevOps che della sottoscrizione di Azure. In questo caso, non sarà necessario creare manualmente la connessione al servizio. In caso contrario, per informazioni su come creare una connessione al servizio di Azure, vedere Creare una connessione al servizio di Azure.

Per informazioni su come creare una connessione al servizio di Azure, vedere Creare una connessione al servizio di Azure.

Distribuzione condizionale

È possibile scegliere di distribuire solo determinate build nel database di Azure.

Per eseguire questa operazione in YAML, è possibile usare una di queste tecniche:

  • Isolare i passaggi di distribuzione in un processo separato e aggiungere una condizione a tale processo.
  • Aggiungere una condizione al passaggio.

Nell'esempio seguente viene illustrato come usare le condizioni dei passaggi per distribuire solo le compilazioni che hanno origine dal ramo principale.

- task: SqlAzureDacpacDeployment@1
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  inputs:
    azureSubscription: '<Azure service connection>'
    ServerName: '<Database server name>'
    DatabaseName: '<Database name>'
    SqlUsername: '<SQL user name>'
    SqlPassword: '<SQL user password>'
    DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'

Per altre informazioni sulle condizioni, vedere Specificare le condizioni.

Altre azioni SQL

La distribuzione di SQL Azure Dacpac potrebbe non supportare tutte le azioni di SQL Server che si desidera eseguire. In questi casi, è sufficiente usare PowerShell o script da riga di comando per eseguire i comandi necessari. Questa sezione illustra alcuni dei casi d'uso comuni per richiamare lo strumento SqlPackage.exe. Come prerequisito per l'esecuzione di questo strumento, è necessario usare un agente self-hosted e avere installato lo strumento nell'agente.

Nota

Se si esegue SQLPackage dalla cartella in cui è installato, è necessario anteporre al percorso & e eseguirne il wrapping tra virgolette doppie.

Sintassi di base

<Path of SQLPackage.exe> <Arguments to SQLPackage.exe>

È possibile usare uno degli script SQL seguenti a seconda dell'azione che si vuole eseguire

Estrazione

Crea un file di snapshot del database (con estensione dacpac) da un server SQL attivo o da un database SQL di Microsoft Azure.

Sintassi dei comandi:

SqlPackage.exe /TargetFile:"<Target location of dacpac file>" /Action:Extract
/SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

or

SqlPackage.exe /action:Extract /tf:"<Target location of dacpac file>"
/SourceConnectionString:"Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=SSPI;Persist Security Info=False;"

Esempio:

SqlPackage.exe /TargetFile:"C:\temp\test.dacpac" /Action:Extract /SourceServerName:"DemoSqlServer.database.windows.net"
 /SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

Help (Guida):

sqlpackage.exe /Action:Extract /?

Pubblica

aggiorna in modo incrementale uno schema di database affinché corrisponda allo schema di un file di origine con estensione dacpac. Se il database non esiste nel server, l'operazione di pubblicazione lo creerà. In caso contrario, verrà aggiornato un database esistente.

Sintassi dei comandi:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Publish /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password> "

Esempio:

SqlPackage.exe /SourceFile:"E:\dacpac\ajyadb.dacpac" /Action:Publish /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb4" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

Help (Guida):

sqlpackage.exe /Action:Publish /?

Esportazione

Esporta un database attivo, inclusi lo schema del database e i dati utente, da SQL Server o database SQL di Microsoft Azure a un pacchetto BACPAC (file bacpac).

Sintassi dei comandi:

SqlPackage.exe /TargetFile:"<Target location for bacpac file>" /Action:Export /SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

Esempio:

SqlPackage.exe /TargetFile:"C:\temp\test.bacpac" /Action:Export /SourceServerName:"DemoSqlServer.database.windows.net"
/SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

Help (Guida):

sqlpackage.exe /Action:Export /?

Import

Importa i dati dello schema e della tabella da un pacchetto BACPAC in un nuovo database utente in un'istanza di SQL Server o database SQL di Microsoft Azure.

Sintassi dei comandi:

SqlPackage.exe /SourceFile:"<Bacpac file location>" /Action:Import /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>"

Esempio:

SqlPackage.exe /SourceFile:"C:\temp\test.bacpac" /Action:Import /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

Help (Guida):

sqlpackage.exe /Action:Import /?

DeployReport

crea un report XML delle modifiche che verrebbero effettuate da un'azione Publish.

Sintassi dei comandi:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:DeployReport /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for deploy report>"

Esempio:

SqlPackage.exe /SourceFile:"E: \dacpac\ajyadb.dacpac" /Action:DeployReport /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\deployReport.xml" 

Help (Guida):

sqlpackage.exe /Action:DeployReport /?

DriftReport

crea un report XML delle modifiche apportate a un database registrato dall'ultima registrazione.

Sintassi dei comandi:

SqlPackage.exe /Action:DriftReport /TargetServerName:"<ServerName>.database.windows.net" /TargetDatabaseName:"<DatabaseName>"
/TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for drift report>"

Esempio:

SqlPackage.exe /Action:DriftReport /TargetServerName:"DemoSqlServer.database.windows.net" /TargetDatabaseName:"Testdb"
/TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\driftReport.xml"

Help (Guida):

sqlpackage.exe /Action:DriftReport /?

Script

crea uno script di aggiornamento incrementale Transact-SQL che aggiorna lo schema di una destinazione affinché corrisponda allo schema di un'origine.

Sintassi dei comandi:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Script /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output SQL script file path>"

Esempio:

SqlPackage.exe /Action:Script /SourceFile:"E:\dacpac\ajyadb.dacpac" /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\test.sql"
/Variables:StagingDatabase="Staging DB Variable value"

Help (Guida):

sqlpackage.exe /Action:Script /?