Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
van toepassing op:SQL Server-
Dit artikel beschrijft hoe je een business logic handler implementeert voor een merge-artikel in SQL Server met behulp van replicatieprogrammering of Replication Management Objects (RMO).
De Microsoft.SqlServer.Replication.BusinessLogicSupport naamruimte implementeert een interface waarmee je complexe bedrijfslogica kunt schrijven om gebeurtenissen te verwerken die optreden tijdens het Merge Replication-synchronisatieproces. Het replicatieproces roept methoden aan in de business logic handler voor elke gewijzigde rij die het tijdens synchronisatie repliceert.
Het algemene proces voor het implementeren van een business logic handler is:
Maak een assembly van de business logic handler.
Registreer de assemblage bij de distributeur.
Implementeer de assembly op de server waarop de Merge Agent wordt uitgevoerd. Voor een pull-abonnement werkt de agent op de abonnee. Voor een push-abonnement draait de agent op de Distributor. Wanneer je websynchronisatie gebruikt, draait de agent op de webserver.
Maak een artikel dat gebruikmaakt van de handler voor bedrijfslogica of een bestaand artikel wijzigt om de handler voor bedrijfslogica te gebruiken.
De business logic handler die u opgeeft, wordt uitgevoerd voor elke rij die wordt gesynchroniseerd. Complexe logica en aanroepen naar andere applicaties of netwerkdiensten kunnen de prestaties beïnvloeden. Zie Voor meer informatie over business logic handlers , Execute Business Logic During Merge Synchronization.
Replicatieprogrammering gebruiken
Een handler voor bedrijfslogica maken en implementeren
Maak in Microsoft Visual Studio een nieuw project voor de .NET-assembly die de code bevat waarmee de business logic handler wordt geïmplementeerd.
Voeg verwijzingen toe aan het project voor de volgende naamruimten.
Verwijzing naar een assembly Locatie Microsoft.SqlServer.Replication.BusinessLogicSupport < schijf>:\Program Files\Microsoft SQL Server\nnn\COM (standaardinstallatie) System.Data GAC (onderdeel van het .NET Framework) System.Data.Common GAC (onderdeel van het .NET Framework) Voeg een klasse toe die de BusinessLogicModule klasse overschrijft.
Implementeer de HandledChangeStates eigenschap om aan te geven welke soorten wijzigingen de handler beheert.
Overschrijf een of meer van de volgende methoden van de BusinessLogicModule klasse:
CommitHandler - aangeroepen wanneer een gegevenswijziging wordt doorgevoerd tijdens de synchronisatie.
DeleteErrorHandler - aangeroepen wanneer er een fout optreedt wanneer een DELETE instructie wordt geüpload of gedownload.
DeleteHandler - aangeroepen wanneer DELETE statements worden geüpload of gedownload.
InsertErrorHandler - aangeroepen wanneer er een fout optreedt wanneer een INSERT instructie wordt geüpload of gedownload.
InsertHandler - aangeroepen wanneer INSERT statements worden geüpload of gedownload.
UpdateConflictsHandler - aangeroepen wanneer conflicterende UPDATE instructies voorkomen bij de Publisher en de Abonnee.
UpdateDeleteConflictHandler - aangeroepen wanneer UPDATE statements in conflict zijn met DELETE statements bij de Publisher en Subscriber.
UpdateErrorHandler - aangeroepen wanneer er een fout optreedt wanneer een UPDATE instructie wordt geüpload of gedownload.
UpdateHandler - aangeroepen wanneer UPDATE statements worden geüpload of gedownload.
Bouw het project om de assembly voor de bedrijfslogica-handler te maken.
Implementeer de assembly in de map waarin het uitvoerbare bestand van de Merge Agent (replmerg.exe) zich bevindt, wat voor een standaardinstallatie is <station>:\Program Files\Microsoft SQL Server\nnn\COM, of installeer deze in de globale assembly-cache (Global Assembly Cache) van .NET. Installeer de assembly alleen in de GAC als applicaties anders dan de Merge Agent toegang tot de assembly vereisen. Gebruik de Global Assembly Cache-tool (Gacutil.exe) die in de .NET Framework SDK wordt geleverd om de assembly in de GAC te installeren.
Opmerking
Je moet op elke server waarop de Merge Agent draait een business logic handler implementeren. Deze eis omvat de IIS-server die de replisapi.dll host bij gebruik van websynchronisatie.
Een handler voor bedrijfslogica registreren
Voer Publisher sp_enumcustomresolvers uit (Transact-SQL) om te verifiëren dat de assembly niet al geregistreerd is als business logic handler.
Voer bij de Distributeur sp_registercustomresolver uit (Transact-SQL), waarbij een vriendelijke naam wordt gespecificeerd voor de business logic handler voor @article_resolver, een waarde van true voor @is_dotnet_assembly, de naam van de assembly voor @dotnet_assembly_name, en de volledig gekwalificeerde naam van de klasse die overschrijft BusinessLogicModule voor @dotnet_class_name.
Opmerking
Als je de assembly niet implementeert in dezelfde map als het uitvoerbare bestand van de Merge Agent, in dezelfde map als de toepassing waarmee de Merge Agent synchroon wordt gestart, of in de globale assemblycache (GAC), moet je voor @dotnet_assembly_name het volledige pad met de assemblynaam opgeven. Bij het gebruik van websynchronisatie moet je de locatie van de assembly op de webserver specificeren.
Een business logic handler gebruiken met een nieuw tabelartikel
- Voer sp_addmergearticle (Transact-SQL) uit om een artikel te definiëren, waarbij u de beschrijvende naam van de business logic handler voor @article_resolver opgeeft. Zie Een artikel definiëren voor meer informatie.
Een business logic handler gebruiken met een bestaand tabelartikel
- Voer sp_changemergearticle uit (Transact-SQL) en specificeer @publication, @article, article_resolver voor @property en de vriendelijke naam van de business logic handler voor @value.
Voorbeelden (replicatieprogrammering)
In dit voorbeeld ziet u een handler voor bedrijfslogica waarmee een auditlogboek wordt gemaakt.
using System;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.SqlServer.Replication.BusinessLogicSupport;
using Microsoft.Samples.SqlServer.BusinessLogicHandler;
namespace Microsoft.Samples.SqlServer.BusinessLogicHandler
{
public class OrderEntryBusinessLogicHandler :
Microsoft.SqlServer.Replication.BusinessLogicSupport.BusinessLogicModule
{
// Variables to hold server names.
private string publisherName;
private string subscriberName;
public OrderEntryBusinessLogicHandler()
{
}
// Implement the Initialize method to get publication
// and subscription information.
public override void Initialize(
string publisher,
string subscriber,
string distributor,
string publisherDB,
string subscriberDB,
string articleName)
{
// Set the Publisher and Subscriber names.
publisherName = publisher;
subscriberName = subscriber;
}
// Declare what types of row changes, conflicts, or errors to handle.
override public ChangeStates HandledChangeStates
{
get
{
// Handle Subscriber inserts, updates and deletes.
return ChangeStates.SubscriberInserts |
ChangeStates.SubscriberUpdates | ChangeStates.SubscriberDeletes;
}
}
public override ActionOnDataChange InsertHandler(SourceIdentifier insertSource,
DataSet insertedDataSet, ref DataSet customDataSet, ref int historyLogLevel,
ref string historyLogMessage)
{
if (insertSource == SourceIdentifier.SourceIsSubscriber)
{
// Build a line item in the audit message to log the Subscriber insert.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("A new order was entered at {0}. " +
"The SalesOrderID for the order is :", subscriberName));
AuditMessage.Append(insertedDataSet.Tables[0].Rows[0]["SalesOrderID"].ToString());
AuditMessage.Append("The order must be shipped by :");
AuditMessage.Append(insertedDataSet.Tables[0].Rows[0]["DueDate"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the inserted data in the Subscriber's data set and
// apply it to the Publisher.
return ActionOnDataChange.AcceptData;
}
else
{
return base.InsertHandler(insertSource, insertedDataSet, ref customDataSet,
ref historyLogLevel, ref historyLogMessage);
}
}
public override ActionOnDataChange UpdateHandler(SourceIdentifier updateSource,
DataSet updatedDataSet, ref DataSet customDataSet, ref int historyLogLevel,
ref string historyLogMessage)
{
if (updateSource == SourceIdentifier.SourceIsPublisher)
{
// Build a line item in the audit message to log the Subscriber update.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("An existing order was updated at {0}. " +
"The SalesOrderID for the order is ", subscriberName));
AuditMessage.Append(updatedDataSet.Tables[0].Rows[0]["SalesOrderID"].ToString());
AuditMessage.Append("The order must now be shipped by :");
AuditMessage.Append(updatedDataSet.Tables[0].Rows[0]["DueDate"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the updated data in the Subscriber's data set and apply it to the Publisher.
return ActionOnDataChange.AcceptData;
}
else
{
return base.UpdateHandler(updateSource, updatedDataSet,
ref customDataSet, ref historyLogLevel, ref historyLogMessage);
}
}
public override ActionOnDataDelete DeleteHandler(SourceIdentifier deleteSource,
DataSet deletedDataSet, ref int historyLogLevel, ref string historyLogMessage)
{
if (deleteSource == SourceIdentifier.SourceIsSubscriber)
{
// Build a line item in the audit message to log the Subscriber deletes.
// Note that the rowguid is the only information that is
// available in the dataset.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("An existing order was deleted at {0}. " +
"The rowguid for the order is ", subscriberName));
AuditMessage.Append(deletedDataSet.Tables[0].Rows[0]["rowguid"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the delete and apply it to the Publisher.
return ActionOnDataDelete.AcceptDelete;
}
else
{
return base.DeleteHandler(deleteSource, deletedDataSet,
ref historyLogLevel, ref historyLogMessage);
}
}
}
}
Imports System
Imports System.Text
Imports System.Data
Imports System.Data.Common
Imports Microsoft.SqlServer.Replication.BusinessLogicSupport
Namespace Microsoft.Samples.SqlServer.BusinessLogicHandler
Public Class OrderEntryBusinessLogicHandler
Inherits BusinessLogicModule
' Variables to hold server names.
Private publisherName As String
Private subscriberName As String
' Implement the Initialize method to get publication
' and subscription information.
Public Overrides Sub Initialize( _
ByVal publisher As String, _
ByVal subscriber As String, _
ByVal distributor As String, _
ByVal publisherDB As String, _
ByVal subscriberDB As String, _
ByVal articleName As String _
)
' Set the Publisher and Subscriber names.
publisherName = publisher
subscriberName = subscriber
End Sub
' Declare what types of row changes, conflicts, or errors to handle.
Public Overrides ReadOnly Property HandledChangeStates() As ChangeStates
Get
' Handle Subscriber inserts, updates and deletes.
Return (ChangeStates.SubscriberInserts Or _
ChangeStates.SubscriberUpdates Or ChangeStates.SubscriberDeletes)
End Get
End Property
Public Overrides Function InsertHandler(ByVal insertSource As SourceIdentifier, _
ByVal insertedDataSet As DataSet, ByRef customDataSet As DataSet, _
ByRef historyLogLevel As Integer, ByRef historyLogMessage As String) _
As ActionOnDataChange
If insertSource = SourceIdentifier.SourceIsSubscriber Then
' Build a line item in the audit message to log the Subscriber insert.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("A new order was entered at {0}. " + _
"The SalesOrderID for the order is :", subscriberName))
AuditMessage.Append(insertedDataSet.Tables(0).Rows(0)("SalesOrderID").ToString())
AuditMessage.Append("The order must be shipped by :")
AuditMessage.Append(insertedDataSet.Tables(0).Rows(0)("DueDate").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the inserted data in the Subscriber's data set and
' apply it to the Publisher.
Return ActionOnDataChange.AcceptData
Else
Return MyBase.InsertHandler(insertSource, insertedDataSet, customDataSet, _
historyLogLevel, historyLogMessage)
End If
End Function
Public Overrides Function UpdateHandler(ByVal updateSource As SourceIdentifier, _
ByVal updatedDataSet As DataSet, ByRef customDataSet As DataSet, _
ByRef historyLogLevel As Integer, ByRef historyLogMessage As String) _
As ActionOnDataChange
If updateSource = SourceIdentifier.SourceIsPublisher Then
' Build a line item in the audit message to log the Subscriber update.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("An existing order was updated at {0}. " + _
"The SalesOrderID for the order is ", subscriberName))
AuditMessage.Append(updatedDataSet.Tables(0).Rows(0)("SalesOrderID").ToString())
AuditMessage.Append("The order must now be shipped by :")
AuditMessage.Append(updatedDataSet.Tables(0).Rows(0)("DueDate").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the updated data in the Subscriber's data set and apply it to the Publisher.
Return ActionOnDataChange.AcceptData
Else
Return MyBase.UpdateHandler(updateSource, updatedDataSet, _
customDataSet, historyLogLevel, historyLogMessage)
End If
End Function
Public Overrides Function DeleteHandler(ByVal deleteSource As SourceIdentifier, _
ByVal deletedDataSet As DataSet, ByRef historyLogLevel As Integer, _
ByRef historyLogMessage As String) As ActionOnDataDelete
If deleteSource = SourceIdentifier.SourceIsSubscriber Then
' Build a line item in the audit message to log the Subscriber deletes.
' Note that the rowguid is the only information that is
' available in the dataset.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("An existing order was deleted at {0}. " + _
"The rowguid for the order is ", subscriberName))
AuditMessage.Append(deletedDataSet.Tables(0).Rows(0)("rowguid").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the delete and apply it to the Publisher.
Return ActionOnDataDelete.AcceptDelete
Else
Return MyBase.DeleteHandler(deleteSource, deletedDataSet, _
historyLogLevel, historyLogMessage)
End If
End Function
End Class
End Namespace
In het volgende voorbeeld wordt een assemblage van een bedrijfslogica-handler geregistreerd bij de Distributeur en wordt een bestaand samenvoegartikel aangepast om deze aangepaste bedrijfslogica te gebruiken.
DECLARE @publication AS sysname;
DECLARE @article AS sysname;
DECLARE @friendlyname AS sysname;
DECLARE @assembly AS nvarchar(500);
DECLARE @class AS sysname;
SET @publication = N'AdvWorksCustomers';
SET @article = N'Customers';
SET @friendlyname = N'OrderEntryLogic';
SET @assembly = N'C:\Program Files\Microsoft SQL Server\120\COM\CustomLogic.dll';
SET @class = N'Microsoft.Samples.SqlServer.BusinessLogicHandler.OrderEntryBusinessLogicHandler';
-- Register the business logic handler at the Distributor.
EXEC sys.sp_registercustomresolver
@article_resolver = @friendlyname,
@resolver_clsid = NULL,
@is_dotnet_assembly = N'true',
@dotnet_assembly_name = @assembly,
@dotnet_class_name = @class;
-- Add an article that uses the business logic handler
-- at the Publisher.
EXEC sp_changemergearticle
@publication = @publication,
@article = @article,
@property = N'article_resolver',
@value = @friendlyname,
@force_invalidate_snapshot = 0,
@force_reinit_subscription = 0;
GO
Replicatiebeheerobjecten (RMO) gebruiken
Een handler voor bedrijfslogica maken
Maak in Microsoft Visual Studio een nieuw project voor de .NET-assembly die de code bevat waarmee de business logic handler wordt geïmplementeerd.
Voeg verwijzingen toe aan het project voor de volgende naamruimten.
Verwijzing naar een assembly Locatie Microsoft.SqlServer.Replication.BusinessLogicSupport < schijf>:\Program Files\Microsoft SQL Server\nnn\COM (standaardinstallatie) System.Data GAC (onderdeel van het .NET Framework) System.Data.Common GAC (onderdeel van het .NET Framework) Voeg een klasse toe die de BusinessLogicModule klasse overschrijft.
Implementeer de HandledChangeStates eigenschap om aan te geven welke soorten wijzigingen de handler beheert.
Overschrijf een of meer van de volgende methoden van de BusinessLogicModule klasse:
CommitHandler - aangeroepen wanneer een gegevenswijziging wordt doorgevoerd tijdens de synchronisatie.
DeleteErrorHandler - aangeroepen als er een fout optreedt tijdens het uploaden of downloaden van een DELETE instructie.
DeleteHandler - aangeroepen wanneer DELETE statements worden geüpload of gedownload.
InsertErrorHandler - aangeroepen als er een fout optreedt wanneer een INSERT instructie wordt geüpload of gedownload.
InsertHandler - aangeroepen wanneer INSERT statements worden geüpload of gedownload.
UpdateConflictsHandler - aangeroepen wanneer conflicterende UPDATE instructies voorkomen bij de Publisher en de Abonnee.
UpdateDeleteConflictHandler - aangeroepen wanneer UPDATE statements in conflict zijn met DELETE statements bij de Publisher en Subscriber.
UpdateErrorHandler - aangeroepen als er een fout optreedt wanneer een UPDATE instructie wordt geüpload of gedownload.
UpdateHandler - aangeroepen wanneer UPDATE statements worden geüpload of gedownload.
Opmerking
De standaardresolver voor het artikel behandelt eventuele artikelconflicten die je aangepaste bedrijfslogica niet expliciet behandelt.
Bouw het project om de assembly voor de bedrijfslogica-handler te maken.
Een handler voor bedrijfslogica registreren
Maak een verbinding met de distributeur met behulp van de ServerConnection klasse.
Maak een exemplaar van de ReplicationServer-klasse. Geef de ServerConnection van stap 1 door.
Roep EnumBusinessLogicHandlers aan en controleer het geretourneerde object ArrayList om te verzekeren dat de assembly nog niet is geregistreerd als handler voor bedrijfslogica.
Maak een exemplaar van de BusinessLogicHandler-klasse. Geef de volgende eigenschappen op:
DotNetAssemblyName - de naam van de .NET-assembly. Als je de assembly niet in dezelfde map als het Merge Agent uitvoerbaar bestand uitrolt, in dezelfde map als de applicatie die synchroon de Merge Agent start, of in de GAC, voeg dan het volledige pad met de assemblynaam op. U moet het volledige pad met de assemblynaam opnemen wanneer u een business logica-handler gebruikt met Web-synchronisatie.
DotNetClassName - de volledig gekwalificeerde naam van de klasse die de business logic handler overschrijft BusinessLogicModule en implementeert.
FriendlyName - een vriendelijke naam die u gebruikt wanneer u toegang hebt tot de bedrijfslogica-handler.
IsDotNetAssembly - een waarde van true.
Een handler voor bedrijfslogica implementeren
- Deploy de assembly op de server waar de Merge Agent draait op de bestandslocatie die werd aangegeven toen je de business logic handler bij de Distributor registreerde. Voor een pull-abonnement werkt de agent op de abonnee. Voor een push-abonnement draait de agent op de Distributor. Wanneer je websynchronisatie gebruikt, draait de agent op de webserver. Als je het volledige pad met de assemblynaam niet toevoegt bij het registreren van de business logic handler, deploy de assembly dan in dezelfde map als het uitvoerbare bestand van de Merge Agent of in dezelfde map als de applicatie die synchroon de Merge Agent start. Als meerdere applicaties dezelfde assembly gebruiken, installeer dan de assembly in de GAC.
Een business logic handler gebruiken met een nieuw tabelartikel
Maak een verbinding met publisher met behulp van de klasse ServerConnection.
Maak een exemplaar van de MergeArticle-klasse. Stel de volgende eigenschappen in:
De naam van het artikel voor Name.
De naam van de publicatie voor PublicationName.
De naam van de publicatiedatabase voor DatabaseName.
De beschrijvende naam van de handler voor bedrijfslogica (FriendlyName).ArticleResolver
Roep de Create methode aan. Zie Een artikel definiëren voor meer informatie.
Een business logic handler gebruiken met een bestaand tabelartikel
Maak een verbinding met publisher met behulp van de klasse ServerConnection.
Maak een exemplaar van de MergeArticle-klasse.
Stel de eigenschappen Name, PublicationNameen DatabaseName in.
Stel de verbinding in vanuit stap 1 voor de ConnectionContext eigenschap.
Roep de LoadProperties methode aan om de eigenschappen van het object op te halen. Als deze methode false oplevert, heb je de eigenschappen van het artikel in stap 3 verkeerd gedefinieerd, of bestaat het artikel niet. Zie Artikeleigenschappen weergeven en wijzigen voor meer informatie.
Stel de vriendelijke naam van de bedrijfslogica-handler in voor ArticleResolver. Deze waarde is de FriendlyName eigenschap die je specificeert bij het registreren van de business logic handler.
Voorbeelden (RMO)
Dit voorbeeld is een zakelijke logische handler die informatie registreert over invoegingen, updates en verwijderingen bij de abonnee.
using System;
using System.Text;
using System.Data;
using System.Data.Common;
using Microsoft.SqlServer.Replication.BusinessLogicSupport;
using Microsoft.Samples.SqlServer.BusinessLogicHandler;
namespace Microsoft.Samples.SqlServer.BusinessLogicHandler
{
public class OrderEntryBusinessLogicHandler :
Microsoft.SqlServer.Replication.BusinessLogicSupport.BusinessLogicModule
{
// Variables to hold server names.
private string publisherName;
private string subscriberName;
public OrderEntryBusinessLogicHandler()
{
}
// Implement the Initialize method to get publication
// and subscription information.
public override void Initialize(
string publisher,
string subscriber,
string distributor,
string publisherDB,
string subscriberDB,
string articleName)
{
// Set the Publisher and Subscriber names.
publisherName = publisher;
subscriberName = subscriber;
}
// Declare what types of row changes, conflicts, or errors to handle.
override public ChangeStates HandledChangeStates
{
get
{
// Handle Subscriber inserts, updates and deletes.
return ChangeStates.SubscriberInserts |
ChangeStates.SubscriberUpdates | ChangeStates.SubscriberDeletes;
}
}
public override ActionOnDataChange InsertHandler(SourceIdentifier insertSource,
DataSet insertedDataSet, ref DataSet customDataSet, ref int historyLogLevel,
ref string historyLogMessage)
{
if (insertSource == SourceIdentifier.SourceIsSubscriber)
{
// Build a line item in the audit message to log the Subscriber insert.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("A new order was entered at {0}. " +
"The SalesOrderID for the order is :", subscriberName));
AuditMessage.Append(insertedDataSet.Tables[0].Rows[0]["SalesOrderID"].ToString());
AuditMessage.Append("The order must be shipped by :");
AuditMessage.Append(insertedDataSet.Tables[0].Rows[0]["DueDate"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the inserted data in the Subscriber's data set and
// apply it to the Publisher.
return ActionOnDataChange.AcceptData;
}
else
{
return base.InsertHandler(insertSource, insertedDataSet, ref customDataSet,
ref historyLogLevel, ref historyLogMessage);
}
}
public override ActionOnDataChange UpdateHandler(SourceIdentifier updateSource,
DataSet updatedDataSet, ref DataSet customDataSet, ref int historyLogLevel,
ref string historyLogMessage)
{
if (updateSource == SourceIdentifier.SourceIsPublisher)
{
// Build a line item in the audit message to log the Subscriber update.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("An existing order was updated at {0}. " +
"The SalesOrderID for the order is ", subscriberName));
AuditMessage.Append(updatedDataSet.Tables[0].Rows[0]["SalesOrderID"].ToString());
AuditMessage.Append("The order must now be shipped by :");
AuditMessage.Append(updatedDataSet.Tables[0].Rows[0]["DueDate"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the updated data in the Subscriber's data set and apply it to the Publisher.
return ActionOnDataChange.AcceptData;
}
else
{
return base.UpdateHandler(updateSource, updatedDataSet,
ref customDataSet, ref historyLogLevel, ref historyLogMessage);
}
}
public override ActionOnDataDelete DeleteHandler(SourceIdentifier deleteSource,
DataSet deletedDataSet, ref int historyLogLevel, ref string historyLogMessage)
{
if (deleteSource == SourceIdentifier.SourceIsSubscriber)
{
// Build a line item in the audit message to log the Subscriber deletes.
// Note that the rowguid is the only information that is
// available in the dataset.
StringBuilder AuditMessage = new StringBuilder();
AuditMessage.Append(String.Format("An existing order was deleted at {0}. " +
"The rowguid for the order is ", subscriberName));
AuditMessage.Append(deletedDataSet.Tables[0].Rows[0]["rowguid"].ToString());
// Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString();
// Set the history log level to the default verbose level.
historyLogLevel = 1;
// Accept the delete and apply it to the Publisher.
return ActionOnDataDelete.AcceptDelete;
}
else
{
return base.DeleteHandler(deleteSource, deletedDataSet,
ref historyLogLevel, ref historyLogMessage);
}
}
}
}
Imports System
Imports System.Text
Imports System.Data
Imports System.Data.Common
Imports Microsoft.SqlServer.Replication.BusinessLogicSupport
Namespace Microsoft.Samples.SqlServer.BusinessLogicHandler
Public Class OrderEntryBusinessLogicHandler
Inherits BusinessLogicModule
' Variables to hold server names.
Private publisherName As String
Private subscriberName As String
' Implement the Initialize method to get publication
' and subscription information.
Public Overrides Sub Initialize( _
ByVal publisher As String, _
ByVal subscriber As String, _
ByVal distributor As String, _
ByVal publisherDB As String, _
ByVal subscriberDB As String, _
ByVal articleName As String _
)
' Set the Publisher and Subscriber names.
publisherName = publisher
subscriberName = subscriber
End Sub
' Declare what types of row changes, conflicts, or errors to handle.
Public Overrides ReadOnly Property HandledChangeStates() As ChangeStates
Get
' Handle Subscriber inserts, updates and deletes.
Return (ChangeStates.SubscriberInserts Or _
ChangeStates.SubscriberUpdates Or ChangeStates.SubscriberDeletes)
End Get
End Property
Public Overrides Function InsertHandler(ByVal insertSource As SourceIdentifier, _
ByVal insertedDataSet As DataSet, ByRef customDataSet As DataSet, _
ByRef historyLogLevel As Integer, ByRef historyLogMessage As String) _
As ActionOnDataChange
If insertSource = SourceIdentifier.SourceIsSubscriber Then
' Build a line item in the audit message to log the Subscriber insert.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("A new order was entered at {0}. " + _
"The SalesOrderID for the order is :", subscriberName))
AuditMessage.Append(insertedDataSet.Tables(0).Rows(0)("SalesOrderID").ToString())
AuditMessage.Append("The order must be shipped by :")
AuditMessage.Append(insertedDataSet.Tables(0).Rows(0)("DueDate").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the inserted data in the Subscriber's data set and
' apply it to the Publisher.
Return ActionOnDataChange.AcceptData
Else
Return MyBase.InsertHandler(insertSource, insertedDataSet, customDataSet, _
historyLogLevel, historyLogMessage)
End If
End Function
Public Overrides Function UpdateHandler(ByVal updateSource As SourceIdentifier, _
ByVal updatedDataSet As DataSet, ByRef customDataSet As DataSet, _
ByRef historyLogLevel As Integer, ByRef historyLogMessage As String) _
As ActionOnDataChange
If updateSource = SourceIdentifier.SourceIsPublisher Then
' Build a line item in the audit message to log the Subscriber update.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("An existing order was updated at {0}. " + _
"The SalesOrderID for the order is ", subscriberName))
AuditMessage.Append(updatedDataSet.Tables(0).Rows(0)("SalesOrderID").ToString())
AuditMessage.Append("The order must now be shipped by :")
AuditMessage.Append(updatedDataSet.Tables(0).Rows(0)("DueDate").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the updated data in the Subscriber's data set and apply it to the Publisher.
Return ActionOnDataChange.AcceptData
Else
Return MyBase.UpdateHandler(updateSource, updatedDataSet, _
customDataSet, historyLogLevel, historyLogMessage)
End If
End Function
Public Overrides Function DeleteHandler(ByVal deleteSource As SourceIdentifier, _
ByVal deletedDataSet As DataSet, ByRef historyLogLevel As Integer, _
ByRef historyLogMessage As String) As ActionOnDataDelete
If deleteSource = SourceIdentifier.SourceIsSubscriber Then
' Build a line item in the audit message to log the Subscriber deletes.
' Note that the rowguid is the only information that is
' available in the dataset.
Dim AuditMessage As StringBuilder = New StringBuilder()
AuditMessage.Append(String.Format("An existing order was deleted at {0}. " + _
"The rowguid for the order is ", subscriberName))
AuditMessage.Append(deletedDataSet.Tables(0).Rows(0)("rowguid").ToString())
' Set the reference parameter to write the line to the log file.
historyLogMessage = AuditMessage.ToString()
' Set the history log level to the default verbose level.
historyLogLevel = 1
' Accept the delete and apply it to the Publisher.
Return ActionOnDataDelete.AcceptDelete
Else
Return MyBase.DeleteHandler(deleteSource, deletedDataSet, _
historyLogLevel, historyLogMessage)
End If
End Function
End Class
End Namespace
In dit voorbeeld wordt een business logic handler geregistreerd bij de Distributeur.
// Specify the Distributor name and business logic properties.
string distributorName = publisherInstance;
string assemblyName = @"C:\Program Files\Microsoft SQL Server\110\COM\CustomLogic.dll";
string className = "Microsoft.Samples.SqlServer.BusinessLogicHandler.OrderEntryBusinessLogicHandler";
string friendlyName = "OrderEntryLogic";
ReplicationServer distributor;
BusinessLogicHandler customLogic;
// Create a connection to the Distributor.
ServerConnection distributorConn = new ServerConnection(distributorName);
try
{
// Connect to the Distributor.
distributorConn.Connect();
// Set the Distributor properties.
distributor = new ReplicationServer(distributorConn);
// Set the business logic handler properties.
customLogic = new BusinessLogicHandler();
customLogic.DotNetAssemblyName = assemblyName;
customLogic.DotNetClassName = className;
customLogic.FriendlyName = friendlyName;
customLogic.IsDotNetAssembly = true;
Boolean isRegistered = false;
// Check if the business logic handler is already registered at the Distributor.
foreach (BusinessLogicHandler registeredLogic
in distributor.EnumBusinessLogicHandlers())
{
if (registeredLogic == customLogic)
{
isRegistered = true;
}
}
// Register the custom logic.
if (!isRegistered)
{
distributor.RegisterBusinessLogicHandler(customLogic);
}
}
catch (Exception ex)
{
// Do error handling here.
throw new ApplicationException(string.Format(
"The {0} assembly could not be registered.",
assemblyName), ex);
}
finally
{
distributorConn.Disconnect();
}
' Specify the Distributor name and business logic properties.
Dim distributorName As String = publisherInstance
Dim assemblyName As String = "C:\Program Files\Microsoft SQL Server\110\COM\CustomLogic.dll"
Dim className As String = "Microsoft.Samples.SqlServer.BusinessLogicHandler.OrderEntryBusinessLogicHandler"
Dim friendlyName As String = "OrderEntryLogic"
Dim distributor As ReplicationServer
Dim customLogic As BusinessLogicHandler
' Create a connection to the Distributor.
Dim distributorConn As ServerConnection = New ServerConnection(distributorName)
Try
' Connect to the Distributor.
distributorConn.Connect()
' Set the Distributor properties.
distributor = New ReplicationServer(distributorConn)
' Set the business logic handler properties.
customLogic = New BusinessLogicHandler()
customLogic.DotNetAssemblyName = assemblyName
customLogic.DotNetClassName = className
customLogic.FriendlyName = friendlyName
customLogic.IsDotNetAssembly = True
Dim isRegistered As Boolean = False
' Check if the business logic handler is already registered at the Distributor.
For Each registeredLogic As BusinessLogicHandler _
In distributor.EnumBusinessLogicHandlers
If registeredLogic Is customLogic Then
isRegistered = True
End If
Next
' Register the custom logic.
If Not isRegistered Then
distributor.RegisterBusinessLogicHandler(customLogic)
End If
Catch ex As Exception
' Do error handling here.
Throw New ApplicationException(String.Format( _
"The {0} assembly could not be registered.", _
assemblyName), ex)
Finally
distributorConn.Disconnect()
End Try
In dit voorbeeld wordt een bestaand artikel gewijzigd om de business logic handler te gebruiken.
// Define the Publisher, publication, and article names.
string publisherName = publisherInstance;
string publicationName = "AdvWorksSalesOrdersMerge";
string publicationDbName = "AdventureWorks2022";
string articleName = "SalesOrderHeader";
// Set the friendly name of the business logic handler.
string customLogic = "OrderEntryLogic";
MergeArticle article = new MergeArticle();
// Create a connection to the Publisher.
ServerConnection conn = new ServerConnection(publisherName);
try
{
// Connect to the Publisher.
conn.Connect();
// Set the required properties for the article.
article.ConnectionContext = conn;
article.Name = articleName;
article.DatabaseName = publicationDbName;
article.PublicationName = publicationName;
// Load the article properties.
if (article.LoadProperties())
{
article.ArticleResolver = customLogic;
}
else
{
// Throw an exception of the article does not exist.
throw new ApplicationException(String.Format(
"{0} is not published in {1}", articleName, publicationName));
}
}
catch (Exception ex)
{
// Do error handling here and rollback the transaction.
throw new ApplicationException(String.Format(
"The business logic handler {0} could not be associated with " +
" the {1} article.",customLogic,articleName), ex);
}
finally
{
conn.Disconnect();
}
' Define the Publisher, publication, and article names.
Dim publisherName As String = publisherInstance
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2022"
Dim articleName As String = "SalesOrderHeader"
' Set the friendly name of the business logic handler.
Dim customLogic As String = "OrderEntryLogic"
Dim article As MergeArticle = New MergeArticle()
' Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)
Try
' Connect to the Publisher.
conn.Connect()
' Set the required properties for the article.
article.ConnectionContext = conn
article.Name = articleName
article.DatabaseName = publicationDbName
article.PublicationName = publicationName
' Load the article properties.
If article.LoadProperties() Then
article.ArticleResolver = customLogic
Else
' Throw an exception of the article does not exist.
Throw New ApplicationException(String.Format( _
"{0} is not published in {1}", articleName, publicationName))
End If
Catch ex As Exception
' Do error handling here and rollback the transaction.
Throw New ApplicationException(String.Format( _
"The business logic handler {0} could not be associated with " + _
" the {1} article.", customLogic, articleName), ex)
Finally
conn.Disconnect()
End Try