如何在订阅者处编写推送订阅创建脚本?

Iai*_*der 7 replication sql-server powershell

我正在尝试设置订阅者对 SQL Server 发布的推送订阅。

我可以使用 Management Studio 中的复制向导在发布者处设置订阅。但是,我更愿意编写相对于订阅者的流程脚本,以便我可以自动部署新的 SQL Server 订阅者实例。

最初,我很乐意在部署前提示输入发布者的名称。如果我可以让它工作,我会寻找一种方法来自动为我的环境注入正确的值。

对于必须在不同发布者上创建多个订阅的 SQL Server 实例,执行此操作的简单方法是什么?

我愿意使用任何受支持的 SQL Server 脚本解决方案:SMO、RMO、Sqlcmd、WMI、PSDrive,甚至是纯 T-SQL。

我试图通过两种方式解决这个问题。第一个是使用 T-SQL 的完整解决方案,但它涉及一些手动步骤。

使用 T-SQL

我在 T-SQL 中有一个手动解决方案。该解决方案基于 Management Studio Replication Script Generator 输出的输出。

使用 Management Studio,我运行以下脚本以生成可在发布者处运行的 T-SQL 脚本:

PRINT N'
EXECUTE MyDatabase.dbo.sp_addsubscription
  @publication = N''MyPublication'',
  @subscriber = ''' + CAST(SERVERPROPERTY('ServerName') AS SYSNAME) + ''',
  @destination_db = ''SubscriberDatabase'',
  @subscription_type = N''Push'',
  @sync_type = N''automatic'',
  @article = N''all'',
  @update_mode = N''read only'',
  @subscriber_type = 0;

EXECUTE MyDatabase.dbo.sp_addpushsubscription_agent
  @publication = N''MyPublication'',
  @subscriber = ''' + CAST(SERVERPROPERTY('ServerName') AS SYSNAME) + ''',
  @subscriber_db = ''SubscriberDatabase'',
  @job_login = null,
  @job_password = null,
  @subscriber_security_mode = 1,
  @frequency_type = 64,
  @frequency_interval = 1,
  @frequency_relative_interval = 1,
  @frequency_recurrence_factor = 0,
  @frequency_subday = 4,
  @frequency_subday_interval = 5,
  @active_start_time_of_day = 0,
  @active_end_time_of_day = 235959,
  @active_start_date = 0,
  @active_end_date = 0,
  @dts_package_location = N''Distributor'';';
Run Code Online (Sandbox Code Playgroud)

在 MYSUBSCRIBER 实例上,输出如下所示:

EXECUTE MyDatabase.dbo.sp_addsubscription
  @publication = N'MyPublication',
  @subscriber = 'MYSUBSCRIBER',
  @destination_db = 'SubscriberDatabase',
  @subscription_type = N'Push',
  @sync_type = N'automatic',
  @article = N'all',
  @update_mode = N'read only',
  @subscriber_type = 0;

EXECUTE MyDatabase.dbo.sp_addpushsubscription_agent
  @publication = N'MyPublication',
  @subscriber = 'MYSUBSCRIBER',
  @subscriber_db = 'SubscriberDatabase',
  @job_login = null,
  @job_password = null,
  @subscriber_security_mode = 1,
  @frequency_type = 64,
  @frequency_interval = 1,
  @frequency_relative_interval = 1,
  @frequency_recurrence_factor = 0,
  @frequency_subday = 4,
  @frequency_subday_interval = 5,
  @active_start_time_of_day = 0,
  @active_end_time_of_day = 235959,
  @active_start_date = 0,
  @active_end_date = 0,
  @dts_package_location = N'Distributor';
Run Code Online (Sandbox Code Playgroud)

我复制输出并在发布者实例上执行脚本以设置订阅。

我想我无法在纯 T-SQL 中自动执行此操作,而无需在运行之前编辑脚本,因为 T-SQL 的设计不处理用户输入。

使用 PowerShell 和 RMO

PowerShell 具有处理用户输入的简单方法,因此这似乎是对自动化过程进行原型设计的好方法。

MSDN 有一个使用 .NET 复制管理对象 (RMO) 设置推送订阅的八步指南

这是前两个步骤:

  1. 使用ServerConnection类创建到发布者的连接。
  2. 使用步骤 1 中的发布者连接创建TransPublication类的实例。指定NameDatabaseNameConnectionContext

我正在尝试将这些步骤转换为 PowerShell 脚本,但我无法通过第 2 步。

在以下代码示例中,我使用虚构的对象名称。我相信这不会影响问题的可回答性,因为当我使用真实对象名称时,错误消息是相同的。

第一次尝试:设置属性

我的第一次尝试是创建 TransReplication 对象,然后设置其属性。代码如下所示:

Add-Type -AssemblyName "Microsoft.SqlServer.Rmo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91";

$Publisher = New-Object Microsoft.SqlServer.Management.Common.ServerConnection MyServer

$Publication = New-Object Microsoft.SqlServer.Replication.TransPublication
$Publication.Name = 'MyPublication'
$Publication.DatabaseName = 'MyDatabase'
$Publication.ConnectionContext = $Publisher
Run Code Online (Sandbox Code Playgroud)

当我执行此脚本时,我看到以下错误:

Exception setting "ConnectionContext": "Cannot convert the "server='(local)';Trusted_Connection=true;multipleactiveresultsets=false" value
 of type "Microsoft.SqlServer.Management.Common.ServerConnection" to type "Microsoft.SqlServer.Management.Common.ServerConnection"."
At line:8 char:14
+ $Publication. <<<< ConnectionContext = $Publisher
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException
Run Code Online (Sandbox Code Playgroud)

看起来它失败了,因为它无法将 type 转换ServerConnection为 type ServerConnection。我不明白这会因上述原因而失败,因为该值已经是所需的类型。

第二次尝试:重载构造函数

我的第二次尝试是在构造函数中指定 TransReplication 对象的属性值。代码如下所示:

Exception setting "ConnectionContext": "Cannot convert the "server='(local)';Trusted_Connection=true;multipleactiveresultsets=false" value
 of type "Microsoft.SqlServer.Management.Common.ServerConnection" to type "Microsoft.SqlServer.Management.Common.ServerConnection"."
At line:8 char:14
+ $Publication. <<<< ConnectionContext = $Publisher
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException
Run Code Online (Sandbox Code Playgroud)

当我执行此脚本时,我看到以下错误:

New-Object : Cannot find an overload for "TransPublication" and the argument count: "3".
At line:5 char:26
+ $Publication = New-Object <<<<  -TypeName Microsoft.SqlServer.Replication.TransPublication 'MyPublication', 'MyDatabase', $Publisher
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Run Code Online (Sandbox Code Playgroud)

看起来 New-Object cmdlet 找不到MSDN 记录的三参数构造函数

public TransPublication(
  string name,
  string databaseName,
  ServerConnection connectionContext
)
Run Code Online (Sandbox Code Playgroud)

参数

据我所知,我正确地重载了​​构造函数。

难道我做错了什么?我的环境有什么异常吗?我最好使用另一种解决方案吗?

Ben*_*hul 2

我将概述一种使用您已有的大部分内容的 T-SQL 方法。

  1. 创建一个表来保存您的出版物信息(对于我编写的解决方案,它只是出版物的名称和标识列)
  2. 创建一个表来保存您的订阅者信息(在我的表中,我有订阅者姓名、订阅者数据库、身份列和引用回出版物的列)
  3. 当您想要创建新订阅时,您可以在订阅者表中添加一个包含相关信息的新行
  4. 在“添加订阅”脚本中,在表和 syssubscriptions 之间进行左连接,以找出表中存在但尚不存在的订阅。将光标放在该信息上,并为每个不存在的订阅创建它。
  5. 添加完所有订阅后,请为每个具有未初始化订阅者的发布调用 sp_startpublication_snapshot。
  6. Fin(又名“你完成了”)。