Restore-SqlDatabase cmdlet中的RelocateFile属性问题

时间:2014-10-15 07:58:30

标签: powershell sqlps

我尝试使用Restore-SqlDatabase cmdlet还原数据库。我需要重新定位文件,但我得到以下错误

Restore-SqlDatabase : Cannot bind parameter 'RelocateFile'. Cannot convert the 
"Microsoft.SqlServer.Management.Smo.RelocateFile" value of type 
"Microsoft.SqlServer.Management.Smo.RelocateFile" to type 
"Microsoft.SqlServer.Management.Smo.RelocateFile".
At line:25 char:108
+ ... e -RelocateFil $RelocateData
+                    ~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (:) [Restore-SqlDatabase], ParameterBindingException
+ FullyQualifiedErrorId CannotConvertArgumentNoMessage,Microsoft.SqlServer.Management.PowerShell.RestoreSqlDatabaseCommand

我的powershell代码看起来像这样

$RelocateData = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("MyDB_Data", "c:\data\MySQLServerMyDB.mdf") 
$RelocateLog = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile("MyDB_Log", "c:\data\MySQLServerMyDB.ldf") 
$file = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile($RelocateData,$RelocateLog) 
$myarr=@($RelocateData,$RelocateLog)
Restore-SqlDatabase -ServerInstance DEV\DEMO -Database "test" -BackupFile $backupfile -RelocateFile $myarr

6 个答案:

答案 0 :(得分:16)

对于解决方案#1,您需要在实例化重新定位文件以使用正确的程序集时指定程序集限定名称。

$RelocateData = New-Object 'Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' -ArgumentList "MyDB_Data", "c:\data\MySQLServerMyDB.mdf"
$RelocateLog = New-Object 'Microsoft.SqlServer.Management.Smo.RelocateFile, Microsoft.SqlServer.SmoExtended, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' -ArgumentList "MyDB_Log", "c:\data\MySQLServerMyDB.ldf"
$file = New-Object Microsoft.SqlServer.Management.Smo.RelocateFile($RelocateData,$RelocateLog) 
$myarr=@($RelocateData,$RelocateLog)
Restore-SqlDatabase -ServerInstance DEV\DEMO -Database "test" -BackupFile $backupfile -RelocateFile $myarr

希望它有所帮助!

答案 1 :(得分:12)

您可以采用与版本无关的方式执行此操作:

$sqlServerSnapinVersion = (Get-Command Restore-SqlDatabase).ImplementingType.Assembly.GetName().Version.ToString()
$assemblySqlServerSmoExtendedFullName = "Microsoft.SqlServer.SmoExtended, Version=$sqlServerSnapinVersion, Culture=neutral, PublicKeyToken=89845dcd8080cc91"

$RelocateData = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, $assemblySqlServerSmoExtendedFullName"('MyDB_Data', 'c:\data\MySQLServerMyDB.mdf')
$RelocateLog = New-Object "Microsoft.SqlServer.Management.Smo.RelocateFile, $assemblySqlServerSmoExtendedFullName"('MyDB_Log', 'c:\data\MySQLServerMyDB.ldf')
$myarr=@($RelocateData,$RelocateLog)
Restore-SqlDatabase -ServerInstance DEV\DEMO -Database "test" -BackupFile $backupfile -RelocateFile $myarr

答案 2 :(得分:9)

这看起来与您加载的SMO版本和Restore-SqlDatabase期望的版本不同。这里可能有两种方法......

  1. 确保版本匹配。
  2. 使用Microsoft.SqlServer.Management.Smo.Restore.SqlRestore方法而不是Restore-SqlDatabase cmdlet。
  3. 我从下面的一个更大的脚本中提取了相关的部分。它在这种形式下未经测试,并且有一些变量,例如$ ServerName,它们被认为可用,但它应该足以让你前进。

        if($useSqlServerAuthentication)
        {
            $passwordSecureString = ConvertTo-SecureString -String $password -AsPlainText -Force;
    
            $serverConnection = new-object Microsoft.SqlServer.Management.Common.ServerConnection $ServerName, $UserName, $passwordSecureString;
    
            $server = new-object Microsoft.SqlServer.Management.Smo.Server $serverConnection;
        }
        else
        {
            $server = new-object Microsoft.SqlServer.Management.Smo.Server $ServerName;
        }
    
        $dataFolder = $server.Settings.DefaultFile;
        $logFolder = $server.Settings.DefaultLog;
    
        if ($dataFolder.Length -eq 0)
        {
            $dataFolder = $server.Information.MasterDBPath;
        }
    
        if ($logFolder.Length -eq 0) 
        {
            $logFolder = $server.Information.MasterDBLogPath;
        }
    
        $backupDeviceItem = new-object Microsoft.SqlServer.Management.Smo.BackupDeviceItem $Path, 'File';
    
        $restore = new-object 'Microsoft.SqlServer.Management.Smo.Restore';
        $restore.Database = $DatabaseName;
        $restore.Devices.Add($backupDeviceItem);
    
        $dataFileNumber = 0;
    
        foreach ($file in $restore.ReadFileList($server)) 
        {
            $relocateFile = new-object 'Microsoft.SqlServer.Management.Smo.RelocateFile';
            $relocateFile.LogicalFileName = $file.LogicalName;
    
            if ($file.Type -eq 'D'){
                if($dataFileNumber -ge 1)
                {
                    $suffix = "_$dataFileNumber";
                }
                else
                {
                    $suffix = $null;
                }
    
                $relocateFile.PhysicalFileName = "$dataFolder\$DatabaseName$suffix.mdf";
    
                $dataFileNumber ++;
            }
            else 
            {
                $relocateFile.PhysicalFileName = "$logFolder\$DatabaseName.ldf";
            }
    
            $restore.RelocateFiles.Add($relocateFile) | out-null;
        }    
    
        $restore.SqlRestore($server);
    

答案 3 :(得分:2)

我在博客中通过更改环境路径变量来解决此问题。 请检查http://powershelldiaries.blogspot.in/2015/08/backup-sqldatabase-restore-sqldatabase.html。 正如我上面提到的,Samuel Dufour"帮助过我。我只是想到了另一种方式。

答案 4 :(得分:2)

使用了@Linhares解决方案,但Snapin程序集的版本15.0.0.0与引用的Microsoft.SqlServer.SmoExtended版本15.100.0.0不匹配。

因此调整了此行,以直接从引用的程序集中获取版本。

$sqlServerSnapinVersion = ((Get-Command Restore-SqlDatabase).ImplementingType.Assembly.GetReferencedAssemblies() | ? { $_.Name -eq "Microsoft.SqlServer.SmoExtended" }).Version.ToString()

答案 5 :(得分:0)

在没有安装SQL Server和Mangement Studio的构建代理上,我遇到了同样的问题。仅PS模块“ SqlServer”可用。

只需在脚本开头添加以下行即可为我解决问题。

(Get-Command Restore-SqlDatabase).ImplementingType.Assembly

此后,程序集将被加载,并且可以使用所有类型。