Wie kann ich die Erstellung eines Push-Abonnements beim Abonnenten ausschreiben?

7

Ich versuche, vom Abonnenten ein Push-Abonnement für eine SQL Server-Publikation einzurichten.

Ich könnte das Abonnement beim Herausgeber mithilfe des Replikationsassistenten in Management Studio einrichten. Ich würde es jedoch vorziehen, den Prozess relativ zum Abonnenten zu skripten, damit ich die Bereitstellung einer neuen SQL Server-Abonnenteninstanz automatisieren kann.

Zunächst frage ich Sie gerne vor der Bereitstellung nach dem Namen des Herausgebers. Wenn dies funktioniert, werde ich nach einer Möglichkeit suchen, den richtigen Wert für meine Umgebung automatisch einzufügen.

Was ist eine einfache Möglichkeit, dies für eine SQL Server-Instanz zu tun, die mehrere Abonnements bei verschiedenen Herausgebern erstellen muss?

Ich bin offen für die Verwendung aller unterstützten SQL Server- Skriptlösungen: SMO, RMO, SQLcmd, WMI, PSDrive und sogar reines T-SQL.

Ich habe versucht, dieses Problem auf zwei Arten zu lösen. Die erste ist eine vollständige Lösung mit T-SQL, die jedoch einige manuelle Schritte umfasst.

Verwenden von T-SQL

Ich habe eine manuelle Lösung in T-SQL. Die Lösung basiert auf der Ausgabe der Management Studio Replication Script Generator-Ausgabe.

Mit Management Studio führe ich das folgende Skript aus, um ein T-SQL-Skript zu generieren, das ich beim Herausgeber ausführen kann:

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'';';

In der MYSUBSCRIBER-Instanz würde die Ausgabe folgendermaßen aussehen:

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';

Ich kopiere die Ausgabe und führe das Skript in der Herausgeberinstanz aus, um das Abonnement einzurichten.

Ich glaube, ich kann dies in reinem T-SQL nicht automatisieren, ohne das Skript vor dem Ausführen zu bearbeiten, da T-SQL von Entwurf keine Benutzereingaben verarbeitet.

Verwenden von PowerShell und RMO

PowerShell bietet einfache Möglichkeiten zur Verarbeitung von Benutzereingaben. Dies scheint also eine gute Möglichkeit zu sein, den Automatisierungsprozess zu prototypisieren.

MSDN verfügt über eine Anleitung in acht Schritten zum Einrichten eines Push-Abonnements mithilfe der .NET Replication Management Objects (RMO).

Hier sind die ersten beiden Schritte:

  1. Erstellen Sie mithilfe der ServerConnection- Klasse eine Verbindung zum Publisher .
  2. Erstellen Sie eine Instanz der TransPublication- Klasse mithilfe der Publisher-Verbindung aus Schritt 1. Geben Sie Name , DatabaseName und ConnectionContext an .

Ich versuche, diese Schritte in ein PowerShell-Skript zu übersetzen, komme aber nicht über Schritt 2 hinaus.

In den folgenden Codebeispielen verwende ich fiktive Objektnamen. Ich glaube, dies hat keinen Einfluss auf die Beantwortbarkeit der Frage, da die Fehlermeldung identisch ist, wenn ich die tatsächlichen Objektnamen verwende.

Erster Versuch: Festlegen der Eigenschaften

Mein erster Versuch besteht darin, das TransReplication-Objekt zu erstellen und dann seine Eigenschaften festzulegen. Der Code sieht folgendermaßen aus:

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

Wenn ich dieses Skript ausführe, wird der folgende Fehler angezeigt:

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

Es sieht so aus, als ob es fehlschlägt, weil es den Typ nicht ServerConnectionin den Typ konvertieren kann ServerConnection. Ich verstehe nicht, wie dies aus dem angegebenen Grund fehlschlagen könnte, da der Wert bereits vom erforderlichen Typ ist.

Zweiter Versuch: Überladen des Konstruktors

Mein zweiter Versuch besteht darin, die Eigenschaftswerte des TransReplication-Objekts im Konstruktor anzugeben. Der Code sieht folgendermaßen aus:

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 'MyPublication', 'MyDatabase', $Publisher

Wenn ich dieses Skript ausführe, wird der folgende Fehler angezeigt:

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

Es sieht so aus, als ob das Cmdlet New-Object den von MSDN dokumentierten Konstruktor mit drei Argumenten nicht finden kann :

public TransPublication(
  string name,
  string databaseName,
  ServerConnection connectionContext
)

Parameter

Soweit ich das beurteilen kann, überlade ich den Konstruktor korrekt.

Mache ich etwas falsch? Hat meine Umgebung etwas Ungewöhnliches? Bin ich besser dran, eine andere Lösung zu verwenden?

Iain Samuel McLean Elder
quelle

Antworten:

2

Ich werde einen T-SQL-Weg skizzieren, der das meiste von dem verwendet, was Sie bereits haben.

  1. Erstellen Sie eine Tabelle mit Ihren Veröffentlichungsinformationen (für die von mir geschriebene Lösung ist dies nur der Name der Veröffentlichung und eine Identitätsspalte).
  2. Erstellen Sie eine Tabelle für Ihre Abonnenteninformationen (in meiner habe ich den Namen des Abonnenten, die Abonnentendatenbank, die Identitätsspalte und eine Spalte, die auf die Veröffentlichung verweist).
  3. Wenn Sie ein neues Abonnement erstellen möchten, fügen Sie eine neue Zeile mit den relevanten Informationen in die Abonnententabelle ein
  4. Führen Sie in Ihrem Skript "Abonnement hinzufügen" eine Linksverknüpfung zwischen Ihrer Tabelle und den Syssubscriptions durch, um herauszufinden, welche Abonnements in Ihrer Tabelle vorhanden sind, aber noch nicht vorhanden sind. Bewegen Sie den Mauszeiger über diese Informationen und erstellen Sie sie für jedes nicht vorhandene Abonnement.
  5. Nachdem Sie alle Abonnements hinzugefügt haben, rufen Sie sp_startpublication_snapshot für jede Publikation auf, deren Abonnenten nicht initialisiert wurden.
  6. Fin (auch bekannt als "du bist fertig").
Ben Thul
quelle
Sind die unterstützenden Objekte in der Herausgeberdatenbank oder in der Abonnentendatenbank vorhanden? Woher weiß der Abonnent, wo er den Verlag findet? Es sieht so aus, als ob Ihre Lösung vom Herausgeber gesteuert wird. Ich suche nach einem Prozess, der vom Abonnenten gesteuert wird, damit ich bei Bedarf Abonnementinstanzen einrichten kann.
Iain Samuel McLean Elder
Alle Objekte befinden sich beim Herausgeber. Wenn Sie jedoch Push-Abonnements einrichten, werden dort ohnehin alle Befehle ausgeführt. Aber selbst wenn es sich um Pull-Abonnements handeln würde, müssten beim Herausgeber einige Befehle ausgeführt werden. Und da Abonnenten kurzlebig sein können, der Verlag jedoch (theoretisch) permanent ist, ist es (für mich) sinnvoll, alle relevanten Informationen beim Verlag zu speichern.
Ben Thul
Alles, was Sie über das Speichern von Objekten und das Ausführen von Befehlen beim Herausgeber sagen, ist sinnvoll. In jeder Implementierung soll der Host des Abonnenten den Prozess steuern, der die Replikation einrichtet. Wenn dies bedeutet, eine Remoteverbindung herzustellen, um gespeicherte Replikationsprozeduren beim Herausgeber aufzurufen, ist dies der Fall. Die Abfolge der Schritte zum Einrichten der vollständigen Instanz mit einem Abonnement kann lang und unterschiedlich sein (SQL Server installieren, globale Servereinstellungen konfigurieren, Benutzerdatenbankschemata erstellen, Anmeldungen mit Windows-Konten verknüpfen, statische Daten einfügen, Veröffentlichungen und Abonnements einrichten).
Iain Samuel McLean Elder
Eine Frage, die ich meiner Meinung nach stellen muss: Warum lassen Sie nur jemanden Ihre Publikation abonnieren? Sehen Sie sich an, welche Berechtigungen zum Ausführen der verschiedenen gespeicherten Replikationsprozeduren erforderlich sind. Sie kennen Ihre Umgebung am besten, aber es scheint, als würden Sie irgendwann um Ärger bitten.
Ben Thul
Nur Administratoren dürfen die Publikation abonnieren, wenn alle Komponenten für die Instanz bereitgestellt werden. Wir experimentieren mit dem Hochfahren von Instanzen auf Anzeigeebene bei Bedarf, daher möchten wir einen einstufigen Prozess. Derzeit dauert es den größten Teil eines Tages, alle Komponenten für eine Instanz bereitzustellen.
Iain Samuel McLean Elder