Bagikan melalui


Menerapkan Pengelola Logika Bisnis untuk Artikel Penggabungan

Berlaku untuk:SQL Server

Topik ini menjelaskan cara menerapkan penanganan logika bisnis untuk artikel penggabungan di SQL Server dengan menggunakan pemrograman replikasi atau Objek Manajemen Replikasi (RMO).

Namespace Microsoft.SqlServer.Replication.BusinessLogicSupport mengimplementasikan antarmuka yang memungkinkan Anda menulis logika bisnis yang kompleks untuk menangani peristiwa yang terjadi selama proses sinkronisasi replikasi penggabungan. Metode dalam handler logika bisnis dapat dipanggil oleh proses replikasi untuk setiap baris yang diubah yang direplikasi selama sinkronisasi.

Proses umum untuk menerapkan handler logika bisnis adalah:

  1. Buat rakitan hander logika bisnis.

  2. Daftarkan assembly di Distributor.

  3. Sebarkan rakitan di server tempat Agen Penggabungan berjalan. Untuk langganan penarikan, agen berjalan pada Pelanggan, dan untuk langganan push, agen berjalan di Distributor. Ketika Anda menggunakan sinkronisasi Web, agen berjalan di server Web.

  4. Buat artikel yang menggunakan penangan logika bisnis atau ubah artikel yang sudah ada untuk menggunakan penangan logika bisnis.

Handler logika bisnis yang Anda tentukan dijalankan untuk setiap baris yang disinkronkan. Logika dan panggilan kompleks ke aplikasi atau layanan jaringan lain dapat memengaruhi performa. Untuk informasi selengkapnya tentang penangan logika bisnis, lihat Menjalankan Logika Bisnis Selama Sinkronisasi Penggabungan.

Dalam Topik Ini

Menggunakan Pemrograman Replikasi

Untuk membuat dan menyebarkan penangan logika bisnis

  1. Di Microsoft Visual Studio, buat proyek baru untuk rakitan .NET yang berisi kode yang mengimplementasikan handler logika bisnis.

  2. Tambahkan referensi ke proyek untuk namespace berikut.

    Referensi Perakitan Lokasi
    Microsoft.SqlServer.Replication.BusinessLogicSupport C:\Program Files\Microsoft SQL Server\nnn\COM (penginstalan default)
    System.Data GAC (komponen .NET Framework)
    System.Data.Common GAC (komponen .NET Framework)
  3. Tambahkan kelas yang mengambil alih BusinessLogicModule kelas.

  4. Terapkan HandledChangeStates properti untuk menunjukkan jenis perubahan yang ditangani.

  5. Ambil alih satu atau beberapa metode BusinessLogicModule kelas berikut:

    • CommitHandler - dipanggil ketika perubahan data dilakukan selama sinkronisasi.

    • DeleteErrorHandler - dipanggil ketika kesalahan terjadi ketika pernyataan DELETE sedang diunggah atau diunduh.

    • DeleteHandler - dipanggil ketika pernyataan DELETE sedang diunggah atau diunduh.

    • InsertErrorHandler - dipanggil ketika kesalahan terjadi ketika pernyataan INSERT sedang diunggah atau diunduh.

    • InsertHandler - dipanggil ketika pernyataan INSERT sedang diunggah atau diunduh.

    • UpdateConflictsHandler - dipanggil saat pernyataan UPDATE yang bertentangan terjadi di Penerbit dan Pelanggan.

    • UpdateDeleteConflictHandler - dipanggil ketika pernyataan UPDATE bertentangan dengan pernyataan DELETE di Penerbit dan Pelanggan.

    • UpdateErrorHandler - dipanggil ketika kesalahan terjadi ketika pernyataan UPDATE sedang diunggah atau diunduh.

    • UpdateHandler - dipanggil ketika pernyataan UPDATE sedang diunggah atau diunduh.

  6. Bangun proyek untuk membuat rakitan handler logika bisnis.

  7. Sebarkan rakitan di direktori yang berisi file Agen Penggabungan yang dapat dieksekusi (replmerg.exe), yang untuk penginstalan default adalah C:\Program Files\Microsoft SQL Server\nnn\COM, atau instal di cache rakitan global .NET (GAC). Anda hanya boleh menginstal rakitan di GAC jika aplikasi selain Agen Penggabungan memerlukan akses ke perakitan. Rakitan dapat diinstal ke GAC menggunakan alat Global Assembly Cache (Gacutil.exe) yang disediakan dalam .NET Framework SDK.

    Catatan

    Handler logika bisnis harus disebarkan di setiap server tempat Agen Penggabungan berjalan, yang mencakup server IIS yang menghosting replisapi.dll saat menggunakan sinkronisasi Web.

Untuk mendaftarkan penangan logika bisnis

  1. Di Publisher, jalankan sp_enumcustomresolvers (Transact-SQL) untuk memverifikasi bahwa rakitan belum terdaftar sebagai penangan logika bisnis.

  2. Di Distributor, jalankan sp_registercustomresolver (Transact-SQL), tentukan nama yang mudah diingat untuk handler logika bisnis untuk @article_resolver, nilai true untuk @is_dotnet_assembly, nama assembly untuk @dotnet_assembly_name, dan nama kelas yang sepenuhnya memenuhi syarat yang mengambil alih BusinessLogicModule untuk @dotnet_class_name.

    Catatan

    Jika rakitan tidak disebarkan di direktori yang sama dengan Agen Penggabungan yang dapat dieksekusi, dalam direktori yang sama dengan aplikasi yang secara sinkron memulai Agen Penggabungan, atau di cache perakitan global (GAC), Anda perlu menentukan jalur lengkap dengan nama rakitan untuk @dotnet_assembly_name. Saat menggunakan sinkronisasi Web, Anda harus menentukan lokasi assembly di server Web.

Untuk menggunakan handler logika bisnis dengan artikel tabel baru

  1. Jalankan sp_addmergearticle (Transact-SQL) untuk menentukan artikel, menentukan nama yang mudah diingat dari handler logika bisnis untuk @article_resolver. Untuk informasi selengkapnya, lihat Menentukan Artikel.

Untuk menggunakan penangan logika bisnis dengan artikel tabel yang sudah ada

  1. Jalankan sp_changemergearticle (Transact-SQL), menentukan @publication, @article, nilai article_resolver untuk @property, dan nama yang ramah dari handler logika bisnis untuk @value.

Contoh (Pemrograman Replikasi)

Contoh ini menunjukkan handler logika bisnis yang membuat log audit.

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

Contoh berikut mendaftarkan rakitan handler logika bisnis di Distributor dan mengubah artikel penggabungan yang ada untuk menggunakan logika bisnis kustom ini.

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

Menggunakan Objek Manajemen Replikasi (RMO)

Untuk membuat handler logika bisnis

  1. Di Microsoft Visual Studio, buat proyek baru untuk rakitan .NET yang berisi kode yang mengimplementasikan handler logika bisnis.

  2. Tambahkan referensi ke proyek untuk namespace berikut.

    Referensi Perakitan Lokasi
    Microsoft.SqlServer.Replication.BusinessLogicSupport C:\Program Files\Microsoft SQL Server\nnn\COM (penginstalan default)
    System.Data GAC (komponen .NET Framework)
    System.Data.Common GAC (komponen .NET Framework)
  3. Tambahkan kelas yang mengambil alih BusinessLogicModule kelas.

  4. Terapkan HandledChangeStates properti untuk menunjukkan jenis perubahan yang ditangani.

  5. Ambil alih satu atau beberapa metode BusinessLogicModule kelas berikut:

    • CommitHandler - dipanggil ketika perubahan data dilakukan selama sinkronisasi.

    • DeleteErrorHandler - dipanggil jika terjadi kesalahan saat pernyataan DELETE sedang diunggah atau diunduh.

    • DeleteHandler - dipanggil ketika pernyataan DELETE sedang diunggah atau diunduh.

    • InsertErrorHandler - dipanggil jika terjadi kesalahan ketika pernyataan INSERT sedang diunggah atau diunduh.

    • InsertHandler - dipanggil ketika pernyataan INSERT sedang diunggah atau diunduh.

    • UpdateConflictsHandler - dipanggil saat pernyataan UPDATE yang bertentangan terjadi di Penerbit dan Pelanggan.

    • UpdateDeleteConflictHandler - dipanggil ketika pernyataan UPDATE bertentangan dengan pernyataan DELETE di Penerbit dan Pelanggan.

    • UpdateErrorHandler - dipanggil jika kesalahan terjadi ketika pernyataan UPDATE sedang diunggah atau diunduh.

    • UpdateHandler - dipanggil ketika pernyataan UPDATE sedang diunggah atau diunduh.

    Catatan

    Setiap konflik artikel yang tidak ditangani secara eksplisit oleh logika bisnis kustom Anda ditangani oleh pemecah masalah default untuk artikel tersebut.

  6. Bangun proyek untuk membuat rakitan handler logika bisnis.

Untuk mendaftarkan penangan logika bisnis

  1. Buat koneksi ke Distributor dengan menggunakan ServerConnection kelas .

  2. Membuat instans kelas ReplicationServer. Teruskan ServerConnection dari langkah 1.

  3. Panggil EnumBusinessLogicHandlers dan periksa objek yang dikembalikan ArrayList untuk memastikan bahwa rakitan belum terdaftar sebagai penangan logika bisnis.

  4. Membuat instans kelas BusinessLogicHandler. Tentukan properti berikut ini:

    • DotNetAssemblyName - nama rakitan .NET. Jika rakitan tidak disebarkan dalam direktori yang sama dengan Agen Penggabungan yang dapat dieksekusi, dalam direktori yang sama dengan aplikasi yang secara sinkron memulai Agen Penggabungan, atau di GAC, Anda harus menyertakan jalur lengkap dengan nama rakitan. Anda harus menyertakan jalur lengkap dengan nama rakitan saat menggunakan penangan logika bisnis dengan sinkronisasi Web.

    • DotNetClassName - nama kelas yang sepenuhnya memenuhi syarat yang mengambil BusinessLogicModule alih dan mengimplementasikan penangan logika bisnis.

    • FriendlyName - nama yang mudah diingat yang Anda gunakan saat mengakses handler logika bisnis.

    • IsDotNetAssembly - nilai benar.

Untuk menyebarkan handler logika bisnis

  1. Sebarkan rakitan di server tempat Agen Penggabungan berjalan di lokasi file yang ditentukan ketika handler logika bisnis terdaftar di Distributor. Untuk langganan penarikan, agen berjalan pada Pelanggan, dan untuk langganan push, agen berjalan di Distributor. Ketika Anda menggunakan sinkronisasi Web, agen berjalan di server Web. Jika jalur lengkap tidak disertakan dengan nama rakitan saat penangan logika bisnis terdaftar, sebarkan rakitan di direktori yang sama dengan Agen Penggabungan yang dapat dieksekusi, dalam direktori yang sama dengan aplikasi yang secara sinkron memulai Agen Penggabungan. Anda dapat menginstal assembly di GAC jika ada beberapa aplikasi yang menggunakan assembly yang sama.

Untuk menggunakan handler logika bisnis dengan artikel tabel baru

  1. Buat koneksi ke Publisher dengan menggunakan ServerConnection kelas .

  2. Membuat instans kelas MergeArticle. Tetapkan properti berikut:

  3. Panggil Create metode. Untuk informasi selengkapnya, lihat Menentukan Artikel.

Untuk menggunakan penangan logika bisnis dengan artikel tabel yang sudah ada

  1. Buat koneksi ke Publisher dengan menggunakan ServerConnection kelas .

  2. Membuat instans kelas MergeArticle.

  3. Atur Nameproperti , PublicationName, dan DatabaseName .

  4. Atur koneksi dari langkah 1 untuk ConnectionContext properti .

  5. LoadProperties Panggil metode untuk mendapatkan properti objek. Jika metode ini mengembalikan false, properti artikel di langkah 3 didefinisikan dengan tidak benar atau artikel tidak ada. Untuk informasi selengkapnya, lihat Menampilkan dan Mengubah Properti Artikel.

  6. Atur nama yang mudah diingat dari handler logika bisnis untuk ArticleResolver. Ini adalah nilai properti yang FriendlyName ditentukan saat mendaftarkan penangan logika bisnis.

Contoh (RMO)

Contoh ini adalah penangan logika bisnis yang mencatat informasi tentang sisipan, pembaruan, dan penghapusan di Pelanggan.

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

Contoh ini mendaftarkan handler logika bisnis di Distributor.

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

Contoh ini mengubah artikel yang sudah ada untuk menggunakan penangan logika bisnis.

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

Lihat Juga

Menerapkan Pemecah Masalah Konflik Kustom untuk Artikel Penggabungan
Men-debug Handler Logika Bisnis (Pemrograman Replikasi)
Praktik Terbaik Keamanan Replikasi
Konsep Objek Manajemen Replikasi