Почему Invoke-SqlCmd работает, а Ado.Net не против базы данных в состоянии восстановления? - PullRequest
0 голосов
/ 18 марта 2019

Вот код Ado.Net (написанный на Powershell):

function ExecuteSqlQuery(
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$ConnectionString,
    [parameter(Mandatory=$true)]
    [string]$Query,
    $QueryTimeout = 30)
{
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection                
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    try 
    {
        $SqlConnection.ConnectionString = $ConnectionString 
        $SqlConnection.Open()

        $SqlCmd.CommandTimeout = $QueryTimeout
        $SqlCmd.CommandText = $Query
        $SqlCmd.Connection = $SqlConnection

        $DataSet = New-Object System.Data.DataSet
        $SqlAdapter.SelectCommand = $SqlCmd        
        [void]$SqlAdapter.Fill($DataSet)

        $res = $null
        if ($DataSet.Tables.Count)
        {
            $res = $DataSet.Tables[$DataSet.Tables.Count - 1]
        }
        $res
    }
    finally 
    {
        $SqlAdapter.Dispose()
        $SqlCmd.Dispose()
        $SqlConnection.Dispose()
    }
}

Существует еще один код, который выполняет следующие действия:

  1. Восстанавливает базу данных с помощью SMO Restore.SqlRestore метод, который оставляет базу данных в состоянии Восстановление ...
  2. Затем применяется некоторый код Sql

Код Sql:

IF 'RESTORING' = (select state_desc from sys.databases where name = '" + $dbname + "')
    restore database [" + $dbname + "] with recovery

ALTER DATABASE [" + $dbname + "] SET RECOVERY Simple WITH NO_WAIT
declare @shrinklogfile varchar(MAX)= N'
use [" + $dbname + "] 
declare @logfilename VARCHAR (MAX) = (select name  from [$dbname].sys.database_files where type_desc=''LOG'')
DBCC shrinkfile(@logfilename,0,truncateonly)
'
exec (@shrinklogfile)

-- get latest backup_finish_date to know the time database is restored to
;WITH LastRestores AS
(
    SELECT
        DatabaseName = [d].[name],
        [d].[create_date],
        [d].[compatibility_level],
        [d].[collation_name],
        r.*,
        RowNum = ROW_NUMBER() OVER (PARTITION BY d.Name ORDER BY r.[restore_date] DESC)
    FROM master.sys.databases d 
    LEFT OUTER JOIN msdb.dbo.[restorehistory] r ON r.[destination_database_name] = d.Name
)
SELECT coalesce(stop_at,restore_date) 
FROM [LastRestores] 
WHERE [RowNum] = 1 and DatabaseName = '" + $dbname + "'

Я понятия не имею, почему исходный код оставляет базу данных в состоянии «Восстановление ...», а затем использует код Sql для завершения восстановления.Но это так.

В любом случае, если код Sql на шаге # 2 выполняется с использованием Invoke-SqlCmd, то все хорошо.Но, если я выполняю тот же код, используя вышеописанную функцию Ado.Net, он не может открыть соединение с базой данных.

Итак, как это делает Invoke-SqlCmd и что можно изменитьв коде Ado.Net выше тоже работать?

...