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-
In dit onderwerp wordt beschreven hoe u een business logic handler implementeert voor een samenvoegartikel in SQL Server met behulp van replicatieprogrammering of RMO (Replication Management Objects).
De Microsoft.SqlServer.Replication.BusinessLogicSupport naamruimte implementeert een interface waarmee u complexe bedrijfslogica kunt schrijven voor het afhandelen van gebeurtenissen die optreden tijdens het synchronisatieproces voor samenvoegingsreplicatie. Methoden in de handler voor bedrijfslogica kunnen worden aangeroepen door het replicatieproces voor elke gewijzigde rij die tijdens de synchronisatie wordt gerepliceerd.
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 wordt de agent uitgevoerd op de Subscriber en voor een push-abonnement wordt de agent uitgevoerd op de Distributor. Wanneer u websynchronisatie gebruikt, wordt de agent uitgevoerd 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 toepassingen of netwerkservices kunnen van invloed zijn op de prestaties. Zie Voor meer informatie over business logic handlers , Execute Business Logic During Merge Synchronization.
In Dit Onderwerp
Als u een bedrijfslogica-handler wilt implementeren voor een samenvoegartikel, gebruikt u:
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 .NET Framework) System.Data.Common GAC (onderdeel van .NET Framework) Voeg een klasse toe die de BusinessLogicModule klasse overschrijft.
Implementeer de HandledChangeStates eigenschap om de typen wijzigingen aan te geven die worden verwerkt.
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 - opgeroepen wanneer DELETE-instructies 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-instructies worden geüpload of gedownload.
UpdateConflictsHandler - aangeroepen wanneer conflicterende UPDATE-instructies optreden bij publisher en abonnee.
UpdateDeleteConflictHandler - aangeroepen wanneer UPDATE-instructies conflicteren met DELETE-instructies bij publisher en abonnee.
UpdateErrorHandler - wordt aangeroepen wanneer er een fout optreedt bij het uploaden of downloaden van een UPDATE-instructie.
UpdateHandler - wordt aangeroepen wanneer Update-instructies 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 andere toepassingen dan de Merge Agent toegang tot de assembly vereisen. De assembly kan worden geïnstalleerd in de GAC met behulp van het hulpprogramma Global Assembly Cache (Gacutil.exe) dat is opgegeven in de .NET Framework SDK.
Opmerking
Een bedrijfslogica-handler moet worden geïmplementeerd op elke server waarop de samenvoegagent wordt uitgevoerd, waaronder de IIS-server die als host fungeert voor de replisapi.dll bij het gebruik van websynchronisatie.
Een handler voor bedrijfslogica registreren
Voer in Publisher sp_enumcustomresolvers (Transact-SQL) uit om te controleren of de assembly nog niet is geregistreerd als een business logic handler.
Voer bij de Distributeur sp_registercustomresolver (Transact-SQL) uit, waarbij u een beschrijvende naam opgeeft voor de logische bedrijfsafhandelaar 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 dat overschrijftBusinessLogicModule voor @dotnet_class_name.
Opmerking
Als de assembly niet wordt geïmplementeerd in dezelfde map als het uitvoerbare bestand van de samenvoegagent, moet u in dezelfde map als de toepassing die synchroon de samenvoegagent start, of in de algemene assemblycache (GAC), het volledige pad opgeven met de assemblynaam voor @dotnet_assembly_name. Wanneer u websynchronisatie gebruikt, moet u de locatie van de assembly op de webserver opgeven.
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 (Transact-SQL) uit, waarbij @publication, @article, een waarde van article_resolver voor @property en de beschrijvende naam van de business logic handler voor @value worden opgegeven.
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 assemblage Locatie Microsoft.SqlServer.Replication.BusinessLogicSupport < schijf>:\Program Files\Microsoft SQL Server\nnn\COM (standaardinstallatie) System.Data GAC (onderdeel van .NET Framework) System.Data.Common GAC (onderdeel van .NET Framework) Voeg een klasse toe die de BusinessLogicModule klasse overschrijft.
Implementeer de HandledChangeStates eigenschap om de typen wijzigingen aan te geven die worden verwerkt.
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-verklaringen 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-instructies worden geüpload of gedownload.
UpdateConflictsHandler - aangeroepen wanneer conflicterende UPDATE-instructies optreden bij publisher en abonnee.
UpdateDeleteConflictHandler - aangeroepen wanneer UPDATE-instructies conflicteren met DELETE-instructies bij publisher en abonnee.
UpdateErrorHandler - aangeroepen als er een fout optreedt wanneer een UPDATE-instructie wordt geüpload of gedownload.
UpdateHandler - wordt aangeroepen wanneer UPDATE-verklaringen worden gedownload of geüpload.
Opmerking
Eventuele artikelconflicten die niet expliciet worden verwerkt door uw aangepaste bedrijfslogica, worden verwerkt door de standaardoplossing voor het artikel.
Bouw het project om de verwerkerassembly voor bedrijfslogica 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 ArrayList object om ervoor te zorgen dat de assembly nog niet als een business logic handler is geregistreerd.
Maak een exemplaar van de BusinessLogicHandler-klasse. Geef de volgende eigenschappen op:
DotNetAssemblyName - de naam van de .NET-assembly. Als de assembly niet is geïmplementeerd in dezelfde map als het uitvoerbare bestand van de Merge Agent, in dezelfde map als de applicatie die de Merge Agent synchroon start, of in de GAC, moet u het volledige pad met de assemblynaam opnemen. 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
- Implementeer de assembly op de server waar de Merge Agent draait, op de bestandslocatie die werd opgegeven toen de businesslogica-handler werd geregistreerd bij de Distributor. Voor een pull-abonnement wordt de agent uitgevoerd op de abonnee en voor een pushabonnement wordt de agent uitgevoerd op de distributeur. Wanneer u websynchronisatie gebruikt, wordt de agent uitgevoerd op de webserver. Als het volledige pad niet is opgenomen in de assemblynaam toen de handler voor bedrijfslogica werd geregistreerd, implementeert u de assembly in dezelfde map als het uitvoerbare bestand van de Merge Agent, in dezelfde map als de toepassing waarmee de samenvoegagent synchroon wordt gestart. U kunt de assembly installeren in de GAC als er meerdere toepassingen zijn die dezelfde assembly gebruiken.
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 onwaar retourneert, zijn de artikeleigenschappen in stap 3 onjuist 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. Dit is de waarde van de FriendlyName eigenschap die is opgegeven bij het registreren van de handler voor bedrijfslogica.
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