【问题标题】:Problems with RelocateFile property in the Restore-SqlDatabase cmdletRestore-SqlDatabase cmdlet 中的 RelocateFile 属性问题
【发布时间】:2020-03-11 23:22:06
【问题描述】:

我尝试使用 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

【问题讨论】:

  • 我想你应该提到当你从 SQL 2012 升级到 SQL 2014 时会发生这个错误。我也会在 Connect 中提出这个错误并让你们知道链接。

标签: powershell sqlps


【解决方案1】:

您可以以独立于版本的方式执行此操作:

$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

【讨论】:

  • 工作就像一个魅力。谢谢
  • 不知道为什么我只使用 5 行来传递路径,但谢谢。我已经找了好几个小时了。
【解决方案2】:

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

$RelocateData = New-Object 'Microsoft.SqlServer.Management.Smo.RelocateFile,Microsoft.SqlServer.SmoExtended,版本=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,版本=11.0.0.0,Culture=neutral,PublicKeyToken=89845dcd8080cc91' -ArgumentList "MyDB_Log","c:\data\MySQLServerMyDB .ldf" $file = 新对象 Microsoft.SqlServer.Management.Smo.RelocateFile($RelocateData,$RelocateLog) $myarr=@($RelocateData,$RelocateLog) 恢复-SqlDatabase -ServerInstance DEV\DEMO -Database "test" -BackupFile $backupfile -RelocateFile $myarr

希望对你有帮助!

【讨论】:

  • 非常有帮助的答案。为我们节省了很多时间和混乱。这个应该是“标记为答案”。但是,你能告诉你在哪里找到这个语法吗?
  • 根据关于 New-Object 的 Powershell 文档,您传递了类的完全限定名称。这里使用的字符串是它的原始形式,包含要使用的程序集的版本,这是这里问题的关键。例如,通过使用下一个答案中使用的 Powershell 命令,您可以找到重定位文件类版本的完全限定名称。
     [appdomain]::CurrentDomain.GetAssemblies() |其中 {$_.FullName -like "*smo*"} | foreach{$_.GetTypes()} |其中{$_.Name -match 'relocatefile'} |选择-Property AssemblyQualifiedName |格式列表
  • 对于 Sql Server 2014,您必须将版本号更改为“12.0.0.0”。
  • 谢谢!我花了 2 个小时试图弄清楚这一点。我认为您还可以将程序集加载到进程空间并简化新对象语法... [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"),然后是 New-Object Microsoft.SqlServer.Management.Smo.RelocateFile
【解决方案3】:

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

  1. 确保版本匹配。
  2. 使用 Microsoft.SqlServer.Management.Smo.Restore.SqlRestore 方法而不是 Restore-SqlDatabase cmdlet。

我从下面的较大脚本中提取了相关部分。它在这种形式中未经测试,并且有一些变量,例如 $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);

【讨论】:

  • 嘿,我有这个问题,而且我有点像 powershell 菜鸟。我如何“确保版本匹配”?
【解决方案4】:

使用 @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】:

    我写了一篇关于通过更改环境路径变量来解决这个问题的博客。 请查看http://powershelldiaries.blogspot.in/2015/08/backup-sqldatabase-restore-sqldatabase.html。 正如我上面提到的,“Samuel Dufour”的回答帮助了我。我只是想到了另一种方法。

    【讨论】:

    • 非常有趣的解释,有助于详细理解问题。
    • 这对我有用,但我认为这些选项中的任何一个都不理想。
    【解决方案6】:

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

    只需在脚本开头添加以下行就解决了我的问题。

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

    之后程序集被加载,所有类型都可以使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-27
      • 2015-07-08
      • 1970-01-01
      相关资源
      最近更新 更多