Udostępnij za pośrednictwem


Zaimplementowanie obsługi logiki biznesowej dla artykułu scalania

Dotyczy:programu SQL Server

W tym temacie opisano sposób implementowania procedury obsługi logiki biznesowej dla artykułu scalania w programie SQL Server przy użyciu programowania replikacji lub obiektów zarządzania replikacją (RMO).

Przestrzeń nazw Microsoft.SqlServer.Replication.BusinessLogicSupport implementuje interfejs, który umożliwia pisanie złożonej logiki biznesowej w celu obsługi zdarzeń występujących podczas synchronizacji replikacji łączącej. Metody w procedurze obsługi logiki biznesowej mogą być wywoływane przez proces replikacji dla każdego zmienionego wiersza replikowanego podczas synchronizacji.

Ogólny proces implementowania procedury obsługi logiki biznesowej to:

  1. Utwórz zestaw obsługi logiki biznesowej.

  2. Zarejestruj zestaw w dystrybutorze.

  3. Wdróż zestaw na serwerze, na którym działa agent scalania. W przypadku subskrypcji typu pull agent działa na subskrybencie, a dla subskrypcji typu push agent działa na dystrybutorze. W przypadku korzystania z synchronizacji sieci Web agent jest uruchamiany na serwerze sieci Web.

  4. Utwórz artykuł, który używa procedury obsługi logiki biznesowej lub zmodyfikuj istniejący artykuł, aby użyć programu obsługi logiki biznesowej.

Określona procedura obsługi logiki biznesowej jest wykonywana dla każdego zsynchronizowanych wierszy. Złożona logika i wywołania innych aplikacji lub usług sieciowych mogą mieć wpływ na wydajność. Aby uzyskać więcej informacji na temat procedur obsługi logiki biznesowej, zobacz Execute Business Logic During Merge Synchronization (Wykonywanie logiki biznesowej podczas synchronizacji scalania).

w tym temacie

Korzystanie z programowania replikacji

Aby stworzyć i wdrożyć obsługę logiki biznesowej

  1. W programie Microsoft Visual Studio utwórz nowy projekt dla zestawu .NET zawierającego kod implementujący procedurę obsługi logiki biznesowej.

  2. Dodaj odwołania do projektu dla następujących przestrzeni nazw.

    Referencja do zgromadzenia Lokalizacja
    Microsoft.SqlServer.Replication.BusinessLogicSupport C:\Program Files\Microsoft SQL Server\nnn\COM (instalacja domyślna)
    System.Data GAC (składnik programu .NET Framework)
    System.Data.Common GAC (składnik programu .NET Framework)
  3. Dodaj klasę, która zastępuje klasę BusinessLogicModule.

  4. Zaimplementuj właściwość HandledChangeStates, aby wskazać typy obsługiwanych zmian.

  5. Zastąpij co najmniej jedną z następujących metod klasy BusinessLogicModule:

    • CommitHandler — wywoływana, gdy zmiana danych zostanie zatwierdzona podczas synchronizacji.

    • DeleteErrorHandler — wywoływana, gdy wystąpi błąd podczas przekazywania lub pobierania instrukcji DELETE.

    • DeleteHandler — wywoływana podczas przesyłania lub pobierania instrukcji DELETE.

    • InsertErrorHandler — wywoływana, gdy wystąpi błąd podczas przekazywania lub pobierania instrukcji INSERT.

    • InsertHandler — wywoływana przy przesyłaniu lub pobieraniu instrukcji INSERT.

    • UpdateConflictsHandler — wywoływany, kiedy dochodzi do konfliktu instrukcji UPDATE między wydawcą a subskrybentem.

    • UpdateDeleteConflictHandler — wywoływana jest, gdy instrukcje UPDATE powodują konflikt z instrukcjami DELETE u wydawcy i subskrybenta.

    • UpdateErrorHandler — wywoływana, gdy wystąpi błąd podczas przekazywania lub pobierania instrukcji UPDATE.

    • UpdateHandler — wywoływana podczas wysyłania lub pobierania instrukcji UPDATE.

  6. Skompiluj projekt, aby utworzyć zestaw obsługi logiki biznesowej.

  7. Wdróż zestaw w katalogu zawierający plik wykonywalny agenta scalania (replmerg.exe), który dla instalacji domyślnej to C:\Program Files\Microsoft SQL Server\nnn\COM lub zainstaluj go w globalnej pamięci podręcznej zestawów platformy .NET (GAC). Zestaw należy zainstalować w GAC tylko wtedy, gdy aplikacje inne niż Agent scalania wymagają dostępu do zestawu. Zestaw można zainstalować w funkcji GAC przy użyciu narzędzia Global Assembly Cache (Gacutil.exe) udostępnionego w zestawie SDK programu .NET Framework.

    Notatka

    Program obsługi logiki biznesowej musi być wdrożony na każdym serwerze, na którym działa agent scalania, w tym na serwerze IIS hostującym replisapi.dll podczas korzystania z synchronizacji sieci Web.

Aby zarejestrować mechanizm logiki biznesowej

  1. W programie Publisher wykonaj sp_enumcustomresolvers (Transact-SQL), aby sprawdzić, czy zestaw nie został jeszcze zarejestrowany jako program obsługi logiki biznesowej.

  2. W dystrybutorze wykonaj sp_registercustomresolver (Transact-SQL), określając przyjazną nazwę programu obsługi logiki biznesowej dla @article_resolver, wartość true dla @is_dotnet_assembly, nazwę zestawu dla @dotnet_assembly_namei w pełni kwalifikowaną nazwę klasy, która zastępuje BusinessLogicModule dla @dotnet_class_name.

    Notatka

    Jeśli zestaw nie jest wdrożony w tym samym katalogu co plik wykonywalny agenta scalania, w tym samym katalogu co aplikacja, która synchronicznie uruchamia agenta scalania lub w globalnej pamięci podręcznej zestawów (GAC), należy określić pełną ścieżkę z nazwą zestawu dla @dotnet_assembly_name. Podczas korzystania z synchronizacji sieci Web należy określić lokalizację zestawu na serwerze sieci Web.

Aby użyć procedury obsługi logiki biznesowej z nowym artykułem tabeli

  1. Wykonaj sp_addmergearticle (Transact-SQL), aby zdefiniować artykuł, określając przyjazną nazwę programu obsługi logiki biznesowej dla @article_resolver. Aby uzyskać więcej informacji, zobacz Define an Article(Definiowanie artykułu).

Aby użyć mechanizmu obsługi logiki biznesowej z istniejącym artykułem tabeli

  1. Wykonaj sp_changemergearticle (Transact-SQL), określając @publication, @article, wartość article_resolver dla @propertyoraz przyjazną nazwę programu obsługi logiki biznesowej dla @value.

Przykłady (programowanie replikacji)

W tym przykładzie przedstawiono procedurę obsługi logiki biznesowej, która tworzy dziennik inspekcji.

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

Poniższy przykład rejestruje zestaw obsługi logiki biznesowej w dystrybutorze i zmienia istniejący artykuł scalania, aby użyć tej niestandardowej logiki biznesowej.

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

Korzystanie z obiektów zarządzania replikacją (RMO)

Aby utworzyć obsługę logiki biznesowej

  1. W programie Microsoft Visual Studio utwórz nowy projekt dla zestawu .NET zawierającego kod implementujący procedurę obsługi logiki biznesowej.

  2. Dodaj odwołania do projektu dla następujących przestrzeni nazw.

    Odwołanie do zestawu Lokalizacja
    Microsoft.SqlServer.Replication.BusinessLogicSupport C:\Program Files\Microsoft SQL Server\nnn\COM (instalacja domyślna)
    System.Data GAC (składnik programu .NET Framework)
    System.Data.Common GAC (składnik programu .NET Framework)
  3. Dodaj klasę, która zastępuje klasę BusinessLogicModule.

  4. Zaimplementuj właściwość HandledChangeStates, aby wskazać typy obsługiwanych zmian.

  5. Zastąpij co najmniej jedną z następujących metod klasy BusinessLogicModule:

    • CommitHandler — wywoływana, gdy zmiana danych zostanie zatwierdzona podczas synchronizacji.

    • DeleteErrorHandler — wywoływana, jeśli wystąpi błąd podczas przekazywania lub pobierania instrukcji DELETE.

    • DeleteHandler — uruchamiana podczas przesyłania lub pobierania instrukcji DELETE.

    • InsertErrorHandler — wywoływana, jeśli wystąpi błąd podczas przekazywania lub pobierania instrukcji INSERT.

    • InsertHandler — wywoływana podczas wysyłania lub pobierania poleceń INSERT.

    • UpdateConflictsHandler — wywoływane, gdy dochodzi do konfliktu instrukcji UPDATE u wydawcy i subskrybenta.

    • UpdateDeleteConflictHandler — wywoływane, gdy instrukcje UPDATE powodują konflikt z instrukcjami DELETE u wydawcy i subskrybenta.

    • UpdateErrorHandler — wywoływana, jeśli wystąpi błąd podczas przekazywania lub pobierania instrukcji UPDATE.

    • UpdateHandler — wywoływana podczas przekazywania lub pobierania instrukcji UPDATE.

    Notatka

    Wszelkie konflikty artykułów, które nie są jawnie obsługiwane przez niestandardową logikę biznesową, są obsługiwane przez domyślny moduł rozpoznawania dla tego artykułu.

  6. Skompiluj projekt, aby utworzyć zestaw obsługi logiki biznesowej.

Aby zarejestrować moduł obsługi logiki biznesowej

  1. Utwórz połączenie z dystrybutorem przy użyciu klasy ServerConnection.

  2. Utwórz wystąpienie klasy ReplicationServer. Przekaż ServerConnection z kroku 1.

  3. Wywołaj EnumBusinessLogicHandlers i sprawdź zwrócony obiekt ArrayList, aby upewnić się, że zestaw nie został jeszcze zarejestrowany jako program obsługi logiki biznesowej.

  4. Utwórz wystąpienie klasy BusinessLogicHandler. Określ następujące właściwości:

    • DotNetAssemblyName — nazwa zestawu .NET. Jeśli zestaw nie jest wdrożony w tym samym katalogu co plik wykonywalny agenta scalania, w tym samym katalogu co aplikacja synchronicznie uruchamia agenta scalania lub w GAC, musisz dołączyć pełną ścieżkę z nazwą zestawu. Należy uwzględnić pełną ścieżkę wraz z nazwą zestawu podczas korzystania z modułu obsługi logiki biznesowej przy synchronizacji z siecią Web.

    • DotNetClassName — w pełni kwalifikowana nazwa klasy, która zastępuje BusinessLogicModule i implementuje procedurę obsługi logiki biznesowej.

    • FriendlyName — przyjazna nazwa używana podczas uzyskiwania dostępu do programu obsługi logiki biznesowej.

    • IsDotNetAssembly — wartość true.

Aby wdrożyć obsługę logiki biznesowej

  1. Wdróż zestaw na serwerze, na którym agent scalania działa w lokalizacji pliku określonej, gdy program obsługi logiki biznesowej został zarejestrowany w dystrybutorze. W przypadku subskrypcji pobierania agent działa na subskrybencie, a dla subskrypcji wypychanej agent działa na dystrybutorze. W przypadku korzystania z synchronizacji sieci Web agent jest uruchamiany na serwerze sieci Web. Jeśli pełna ścieżka nie została dołączona do nazwy zestawu, gdy program obsługi logiki biznesowej został zarejestrowany, wdróż zestaw w tym samym katalogu co plik wykonywalny agenta scalania, w tym samym katalogu co aplikacja, która synchronicznie uruchamia agenta scalania. Zestaw można zainstalować w GAC, jeśli istnieje wiele aplikacji korzystających z tego samego zestawu.

Aby użyć obsługi logiki biznesowej z nowym artykułem tabeli

  1. Utwórz połączenie z programem Publisher przy użyciu klasy ServerConnection.

  2. Utwórz wystąpienie klasy MergeArticle. Ustaw następujące właściwości:

  3. Wywołaj metodę Create. Aby uzyskać więcej informacji, zobacz Define an Article(Definiowanie artykułu).

Aby użyć obsługi logiki biznesowej z istniejącym elementem tabeli

  1. Utwórz połączenie z programem Publisher przy użyciu klasy ServerConnection.

  2. Utwórz wystąpienie klasy MergeArticle.

  3. Ustaw właściwości Name, PublicationNamei DatabaseName.

  4. Ustaw połączenie z kroku 1 dla właściwości ConnectionContext.

  5. Wywołaj metodę LoadProperties, aby uzyskać właściwości obiektu. Jeśli ta metoda zwraca false, właściwości artykułu w kroku 3 zostały niepoprawnie zdefiniowane lub artykuł nie istnieje. Aby uzyskać więcej informacji, zobacz View and Modify Article Properties.

  6. Ustaw przyjazną nazwę programu obsługi logiki biznesowej dla ArticleResolver. Jest to wartość właściwości FriendlyName określonej podczas rejestrowania programu obsługi logiki biznesowej.

Przykłady (RMO)

W tym przykładzie przedstawiono procedurę obsługi logiki biznesowej, która rejestruje informacje o dodaniach, aktualizacjach i usunięciach po stronie subskrybenta.

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

W tym przykładzie zarejestrowano procedurę obsługi logiki biznesowej w dystrybutorze.

// 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

W tym przykładzie wprowadzono zmiany w istniejącym artykule, aby użyć obsługi logiki biznesowej.

// 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