From 648c9bd92d76a0eb5dcb94d818f26625e07c908d Mon Sep 17 00:00:00 2001 From: Andreas Jordan Date: Thu, 13 Aug 2026 18:51:22 +0200 Subject: [PATCH] Install-DbaMaintenanceSolution - Leave the connection of the caller alone The command closed its connection when it was done, no matter whether it had opened it or whether the caller handed one over. Connect-DbaInstance now reports that through -IsNewConnectionReference. The disconnect was also hiding that the cleanup of the existing objects ran through $db.Invoke(), which leaves the connection in that database. The installation of the scripts a few lines below already names the database with Invoke-DbaQuery, so the cleanup now does the same. See #10554 and #10555 (do Install-DbaMaintenanceSolution) Co-Authored-By: Claude Opus 5 (1M context) --- public/Install-DbaMaintenanceSolution.ps1 | 21 +++++++++-- .../Install-DbaMaintenanceSolution.Tests.ps1 | 37 +++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/public/Install-DbaMaintenanceSolution.ps1 b/public/Install-DbaMaintenanceSolution.ps1 index b47c7942331..52d33ab9a65 100644 --- a/public/Install-DbaMaintenanceSolution.ps1 +++ b/public/Install-DbaMaintenanceSolution.ps1 @@ -456,8 +456,17 @@ function Install-DbaMaintenanceSolution { } foreach ($instance in $SqlInstance) { + # Connect-DbaInstance tells us whether it opened a connection for us. We must only close what we opened + # ourselves, because closing a connection of the caller takes their session with it. See #10554. + $isNewConnection = $false + $splatConnect = @{ + SqlInstance = $instance + SqlCredential = $SqlCredential + NonPooledConnection = $true + IsNewConnectionReference = [ref]$isNewConnection + } try { - $server = Connect-DbaInstance -SqlInstance $instance -SqlCredential $SqlCredential -NonPooledConnection + $server = Connect-DbaInstance @splatConnect } catch { Stop-Function -Message "Error occurred while establishing connection to $instance" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } @@ -558,7 +567,9 @@ function Install-DbaMaintenanceSolution { if ($Pscmdlet.ShouldProcess($instance, "Dropping all objects created by Ola's Maintenance Solution")) { Write-ProgressHelper -ExcludePercent -Message "Dropping objects created by Ola's Maintenance Solution" - $null = $db.Invoke($cleanupQuery) + # Invoke-DbaQuery names the database instead of running on the connection of the caller, which + # $db.Invoke() would leave in that database. This is how the installation below runs as well. + $null = Invoke-DbaQuery -SqlInstance $server -Database $Database -Query $cleanupQuery -EnableException } # Remove Ola's Jobs @@ -891,8 +902,10 @@ function Install-DbaMaintenanceSolution { } } - # Close non-pooled connection as this is not done automatically. If it is a reused Server SMO, connection will be opened again automatically on next request. - $null = $server | Disconnect-DbaInstance + if ($isNewConnection) { + # Close non-pooled connection as this is not done automatically. + $null = $server | Disconnect-DbaInstance + } } Write-ProgressHelper -ExcludePercent -Message "Installation complete" diff --git a/tests/Install-DbaMaintenanceSolution.Tests.ps1 b/tests/Install-DbaMaintenanceSolution.Tests.ps1 index 5c1c470f19f..a80d3955ec8 100644 --- a/tests/Install-DbaMaintenanceSolution.Tests.ps1 +++ b/tests/Install-DbaMaintenanceSolution.Tests.ps1 @@ -193,6 +193,43 @@ Describe $CommandName -Tag IntegrationTests { } } + Context "The connection of the caller is left alone (#10554)" { + BeforeAll { + $PSDefaultParameterValues["*-Dba*:EnableException"] = $true + + $callerServer = Connect-DbaInstance -SqlInstance $TestConfig.InstanceMulti1 -NonPooledConnection + $null = $callerServer.ConnectionContext.ExecuteNonQuery("CREATE TABLE #dbatoolsci_marker (id INT)") + + # ReplaceExisting takes the code path that drops the existing objects, jobs are left out so that no + # SQL Agent command touches the connection - those are separate commands, see #10555. + $splatInstall = @{ + SqlInstance = $callerServer + Database = "tempdb" + BackupLocation = "NUL" + ReplaceExisting = $true + } + $null = Install-DbaMaintenanceSolution @splatInstall + + $PSDefaultParameterValues.Remove("*-Dba*:EnableException") + } + + AfterAll { + $PSDefaultParameterValues["*-Dba*:EnableException"] = $true + + $null = $callerServer | Disconnect-DbaInstance + + $PSDefaultParameterValues.Remove("*-Dba*:EnableException") + } + + It "leaves the connection open, so the session survives" { + { $callerServer.ConnectionContext.ExecuteScalar("SELECT COUNT(*) FROM #dbatoolsci_marker") } | Should -Not -Throw + } + + It "leaves the connection in the database it was on" { + $callerServer.ConnectionContext.ExecuteScalar("SELECT DB_NAME()") | Should -Be "master" + } + } + Context "Additional backup parameters all enabled" { AfterEach { Invoke-DbaQuery -SqlInstance $TestConfig.InstanceMulti2 -Query $jobStep.Command -NoExec -EnableException