Многократные ошибки цикла и подключения Invoke-SQLCmd AzureSQL - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь перебрать invoke-sqlcmd для нескольких баз данных AzureSQL через Azure Automation. Первый элемент в цикле выполняется, но все остальные завершаются с ошибкой:

Invoke-Sqlcmd: произошла ошибка, связанная с сетью или экземпляром при установлении соединения с SQL Server. Сервера не было найден или недоступен Убедитесь, что имя экземпляра правильное и что SQL Server настроен для разрешения удаленных подключений. (поставщик: поставщик именованных каналов, ошибка: 40 - не удалось открыть подключение к SQL Server)

Я предполагаю, что мне нужно закрыть соединение от первого invoke-sqlcmd перед выполнением следующего, но я не нашел прямого метода для достижения этого с invoke-sqlcmd. Вот мой цикл:

param(      
# Parameters to Pass to PowerShell Scripts
[parameter(Mandatory=$true)][String] $azureSQLServerName = "myazuresql",        
[parameter(Mandatory=$true)][String] $azureSQLCred = "myazureautosqlcred"        
        )

# DB Name Array
$dbnamearray = @("database1","database2","database3")
$dbnamearray

# Datatable Name
$tabName = "RunbookTable"

#Create Table object
$table = New-Object system.Data.DataTable "$tabName"

#Define Columns
$col1 = New-Object system.Data.DataColumn dbname,([string])

#Add the Columns
$table.columns.add($col1)

# Add Row and Values for dname Column
ForEach ($db in $dbnamearray) 
{
$row = $table.NewRow()
$row.dbname = $db
#Add the row to the table
$table.Rows.Add($row)
}

#Display the table
$table | format-table -AutoSize

# Loop through the datatable using the values per column 
$table | ForEach-Object {

# Set loop variables as these are easier to pass then $_.
$azureSQLDatabaseName = $_.dbname

# Execute SQL Query Against Azure SQL
$azureSQLServerName = $azureSQLServerName + ".database.windows.net"
$Cred = Get-AutomationPSCredential -Name $azureSQLCred
$SQLOutput = $(Invoke-Sqlcmd -ServerInstance $azureSQLServerName -Username $Cred.UserName -Password $Cred.GetNetworkCredential().Password -Database $azureSQLDatabaseName -Query "SELECT * FROM INFORMATION_SCHEMA.TABLES " -QueryTimeout 65535 -ConnectionTimeout 60 -Verbose) 4>&1
Write-Output $SQLOutput
}

Ответы [ 3 ]

0 голосов
/ 19 мая 2018

Кажется, что вы добавляете .database.windows.net к имени сервера внутри цикла. Наверное, поэтому он работает только для первой итерации.

Просто переместите эту строку:

$azureSQLServerName = $azureSQLServerName + ".database.windows.net"

до этой строки:

$table | ForEach-Object {
0 голосов
/ 21 мая 2018

Я сталкивался с той же проблемой ранее, когда делал что-то с базой данных Azure SQL. Вы можете попробовать это

1. Создать учетную запись для автоматизации

New-AzureRmAutomationAccount -ResourceGroupName $resourceGroupName -Name $automationAccountName -Location $location

2. Настройте учетную запись автоматизации для работы с

Set-AzureRmAutomationAccount -Name $automationAccountName -ResourceGroupName $resourceGroupName

3. Создать / импортировать Runbook

Здесь у нас уже есть готовая книга запусков, поэтому мы импортируем ее. Вот код Runbook

workflow runbookNameValue
{
    inlinescript
    {
        $MasterDatabaseConnection = New-Object System.Data.SqlClient.SqlConnection
        $MasterDatabaseConnection.ConnectionString = "ConnectionStringValue"

        # Open connection to Master DB
        $MasterDatabaseConnection.Open()

        # Create command
        $MasterDatabaseCommand = New-Object System.Data.SqlClient.SqlCommand
        $MasterDatabaseCommand.Connection = $MasterDatabaseConnection
        $MasterDatabaseCommand.CommandText = "Exec stored procedure"

        # Execute the query
        $MasterDatabaseCommand.ExecuteNonQuery()

        # Close connection to Master DB
        $MasterDatabaseConnection.Close() 
    }
}

4. Импорт

Import-AzureRMAutomationRunbook -Name $runBookName -Path $scriptPath -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -Type PowerShell

Надеюсь, это поможет. Вместо использования Invoke-Sqlcmd используйте $MasterDatabaseCommand.ExecuteNonQuery(), как я указал в runbook. Это будет работать

0 голосов
/ 16 мая 2018

Вы можете попробовать установить каждое соединение как задание powershell . Это решило очень похожую проблему, с которой я столкнулся некоторое время назад. Send-MailMessage закрывает каждое второе соединение при использовании вложений Если вы хотите прочитать объяснение. По сути, если вы не можете использовать метод .Close (), вы можете принудительно закрыть соединений, завершив весь сеанс для каждого запуска. В идеальном мире командлет справился бы со всем этим за вас, но не все было создано идеально.

# Loop through the datatable using the values per column 
$table | ForEach-Object {

# Set loop variables as these are easier to pass then $_.
$azureSQLDatabaseName = $_.dbname

# Execute SQL Query Against Azure SQL
$azureSQLServerName = $azureSQLServerName + ".database.windows.net"
$Cred = Get-AutomationPSCredential -Name $azureSQLCred

# Pass in the needed parameters via -ArgumentList and start the job.
Start-Job -ScriptBlock { Write-Output $(Invoke-Sqlcmd -ServerInstance $args[0] -Username $args[1].UserName -Password $args[1].GetNetworkCredential().Password -Database $args[0] -Query "SELECT * FROM INFORMATION_SCHEMA.TABLES " -QueryTimeout 65535 -ConnectionTimeout 60 -Verbose) 4>&1 } -ArgumentList $azureSQLServerName, $Cred | Wait-Job | Receive-Job

}

Это не проверено, так как у меня нет сервера для подключения, но, возможно, немного поработав, вы сможете что-то из него сделать.

...