Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Aplica-se a:SQL Server
Este tópico descreve como implementar um manipulador de lógica de negócios para um artigo de mesclagem no SQL Server usando programação de replicação ou RMO (Replication Management Objects).
O namespace Microsoft.SqlServer.Replication.BusinessLogicSupport implementa uma interface que permite escrever lógica complexa de negócios para manipular eventos que ocorrem durante o processo de sincronização da replicação por mesclagem. Os métodos no manipulador de lógica de negócios podem ser invocados pelo processo de replicação para cada linha alterada replicada durante a sincronização.
O processo geral para implementar um manipulador de lógica de negócios é:
Crie a assemblagem do manipulador de lógica de negócios.
Registe a montagem do produto no Distribuidor.
Implante o assembly no servidor no qual o Merge Agent é executado. Para uma assinatura pull, o agente é executado no Assinante e, para uma assinatura push, o agente é executado no Distribuidor. Quando você estiver usando a sincronização da Web, o agente é executado no servidor Web.
Crie um artigo que use o manipulador de lógica de negócios ou modifique um artigo existente para usar o manipulador de lógica de negócios.
O manipulador de lógica de negócios especificado é executado para cada linha sincronizada. A lógica complexa e as chamadas para outros aplicativos ou serviços de rede podem afetar o desempenho. Para obter mais informações sobre manipuladores de lógica de negócios, consulte Executar lógica de negócios durante a sincronização de mesclagem.
Neste tópico
Para implementar um manipulador de lógica de negócios para um artigo de mesclagem, usando:
RMO (Replication Management Objects, objetos de gerenciamento de replicação)
Usando a programação de replicação
Para criar e implantar um manipulador de lógica de negócios
No Microsoft Visual Studio, crie um novo projeto para o assembly .NET que contém o código que implementa o manipulador de lógica de negócios.
Adicione referências ao projeto para os namespaces a seguir.
Referência de montagem Localização Microsoft.SqlServer.Replication.BusinessLogicSupport < unidade>:\Arquivos de Programas\Microsoft SQL Server\nnn\COM (instalação padrão) System.Data GAC (componente do .NET Framework) System.Data.Common GAC (componente do .NET Framework) Adicione uma classe que substitua a classe BusinessLogicModule.
Implemente a propriedade HandledChangeStates para indicar os tipos de alterações que são tratadas.
Substitua um ou mais dos seguintes métodos da classe BusinessLogicModule:
CommitHandler - invocado quando uma alteração de dados é confirmada durante a sincronização.
DeleteErrorHandler - invocado se ocorrer um erro durante o carregamento ou transferência de uma declaração DELETE.
DeleteHandler - chamados quando as instruções DELETE estão a ser carregadas ou descarregadas.
InsertErrorHandler - invocado quando ocorre um erro durante o carregamento ou descarregamento de uma declaração INSERT.
InsertHandler - acionado quando as instruções INSERT estão a ser enviadas ou transferidas.
UpdateConflictsHandler - invocado quando ocorrem instruções UPDATE conflitantes no Publisher e no Subscriber.
UpdateDeleteConflictHandler - invocado quando as instruções UPDATE entram em conflito com as instruções DELETE no Publicador e no Subscritor.
UpdateErrorHandler - invocados quando ocorre um erro durante o upload ou descarregamento de uma UPDATE instrução.
UpdateHandler - invocado quando as instruções UPDATE estão a ser carregadas ou descarregadas.
Compile o projeto para criar o assembly do manipulador de lógica de negócios.
Implante o assembly no diretório que contém o arquivo executável do Merge Agent (replmerg.exe), que para uma instalação padrão é <drive>:\Program Files\Microsoft SQL Server\nnn\COM, ou instale-o no cache de assembly global (GAC) do .NET. Você só deve instalar o assembly no GAC se aplicações diferentes do Merge Agent requererem acesso ao assembly. O assembly pode ser instalado no GAC usando a ferramenta Global Assembly Cache (Gacutil.exe) fornecida no SDK do .NET Framework.
Observação
Um manipulador de lógica de negócios deve ser implantado em cada servidor no qual o Merge Agent é executado, o que inclui o servidor IIS que hospeda o replisapi.dll ao usar a sincronização da Web.
Para registrar um manipulador de lógica de negócios
No Publisher, execute sp_enumcustomresolvers (Transact-SQL) para verificar se o assembly ainda não foi registrado como um manipulador de lógica de negócios.
No Distribuidor, execute sp_registercustomresolver (Transact-SQL), especificando um nome amigável para o manipulador de lógica de negócios para @article_resolver, um valor de verdadeiro para @is_dotnet_assembly, o nome do assembly para @dotnet_assembly_namee o nome totalmente qualificado da classe que substitui BusinessLogicModule para @dotnet_class_name.
Observação
Se o assembly não for implantado no mesmo diretório que o executável do Merge Agent, no mesmo diretório do aplicativo que inicia o Merge Agent de forma síncrona ou no cache de assembly global (GAC), você precisará especificar o caminho completo com o nome do assembly para @dotnet_assembly_name. Ao usar a sincronização da Web, deve-se especificar a localização do assembly no servidor Web.
Para usar um manipulador de lógica de negócios com um novo artigo de tabela
- Execute sp_addmergearticle (Transact-SQL) para definir um artigo, especificando o nome amigável do manipulador de lógica de negócios para @article_resolver. Para obter mais informações, consulte Definição de um artigo.
Para usar um manipulador de lógica de negócios com um elemento de tabela existente
- Execute sp_changemergearticle (Transact-SQL), especificando @publication, @article, um valor de article_resolver para @propertye o nome amigável do manipulador de lógica de negócios para @value.
Exemplos (programação de replicação)
Este exemplo mostra um manipulador de lógica de negócios que cria um log de auditoria.
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
O exemplo a seguir regista um conjunto de manipulador de lógica empresarial no Distribuidor e altera um artigo de fusão existente para usar essa lógica de negócios personalizada.
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
Usando RMO (Replication Management Objects, objetos de gerenciamento de replicação)
Para criar um manipulador de lógica de negócios
No Microsoft Visual Studio, crie um novo projeto para o assembly .NET que contém o código que implementa o manipulador de lógica de negócios.
Adicione referências ao projeto para os namespaces a seguir.
Referência de montagem Localização Microsoft.SqlServer.Replication.BusinessLogicSupport < unidade>:\Arquivos de Programas\Microsoft SQL Server\nnn\COM (instalação padrão) System.Data GAC (componente do .NET Framework) System.Data.Common GAC (componente do .NET Framework) Adicione uma classe que substitua a classe BusinessLogicModule.
Implemente a propriedade HandledChangeStates para indicar os tipos de alterações que são tratadas.
Substitua um ou mais dos seguintes métodos da classe BusinessLogicModule:
CommitHandler - invocado quando uma alteração de dados é confirmada durante a sincronização.
DeleteErrorHandler - invocado se ocorrer um erro enquanto uma DELETE instrução está a ser carregada ou descarregada.
DeleteHandler - chamado quando as declarações DELETE estão a ser carregadas ou transferidas.
InsertErrorHandler - invocado se ocorrer um erro quando uma INSERT instrução está a ser carregada ou descarregada.
InsertHandler - chamado quando as declarações INSERT estão a ser carregadas ou descarregadas.
UpdateConflictsHandler- invocados quando ocorrem declarações conflitantes UPDATE no Publisher e no Subscritor.
UpdateDeleteConflictHandler - invocado quando as instruções UPDATE entram em conflito com as instruções DELETE no Publicador e no Subscritor.
UpdateErrorHandler - invocado se ocorrer um erro quando uma UPDATE instrução está a ser carregada ou descarregada.
UpdateHandler - chamado quando as instruções UPDATE estão a ser carregadas ou descarregadas.
Observação
Quaisquer conflitos de artigo não tratados explicitamente pela sua lógica de negócios personalizada são tratados pelo resolvedor padrão do artigo.
Compile o projeto para criar o assembly do manipulador de lógica de negócios.
Para registrar um manipulador de lógica de negócios
Crie uma conexão com o Distribuidor usando a classe ServerConnection.
Crie uma instância da classe ReplicationServer. Passe o ServerConnection do passo 1.
Chame EnumBusinessLogicHandlers e verifique o objeto ArrayList retornado para garantir que o assembly ainda não tenha sido registrado como um manipulador de lógica de negócios.
Crie uma instância da classe BusinessLogicHandler. Especifique as seguintes propriedades:
DotNetAssemblyName - o nome da montagem .NET. Se o assembly não for implantado no mesmo diretório que o executável do Merge Agent, no mesmo diretório do aplicativo que inicia o Merge Agent de forma síncrona ou no GAC, você deverá incluir o caminho completo com o nome do assembly. Você deve incluir o caminho completo com o nome do assembly ao usar um manipulador de lógica de negócios com sincronização da Web.
DotNetClassName - o nome totalmente qualificado da classe que substitui BusinessLogicModule e implementa o manipulador de lógica de negócios.
FriendlyName - um nome amigável que você usa quando acessa o manipulador de lógica de negócios.
IsDotNetAssembly - um valor de verdadeiro.
Para implantar um manipulador de lógica de negócios
- Implante o conjunto no servidor onde o Merge Agent é executado no local especificado do arquivo quando o manipulador de lógica de negócios foi registrado no Distribuidor. Para uma assinatura pull, o agente é executado no Assinante e, para uma assinatura push, o agente é executado no Distribuidor. Quando você estiver usando a sincronização da Web, o agente é executado no servidor Web. Se o caminho completo não foi incluído com o nome do assembly quando o manipulador de lógica de negócios foi registrado, implante o assembly no mesmo diretório que o executável do Merge Agent, no mesmo diretório do aplicativo que inicia o Merge Agent de forma síncrona. Pode instalar a assemblagem no GAC se houver várias aplicações que utilizem a mesma assemblagem.
Para usar um manipulador de lógica de negócios com um novo artigo de tabela
Crie uma conexão com o Publisher usando a classe ServerConnection.
Crie uma instância da classe MergeArticle. Defina as seguintes propriedades:
O nome do artigo para Name.
O nome da publicação para PublicationName.
O nome do banco de dados de publicações para DatabaseName.
O nome amigável do manipulador de lógica de negócios (FriendlyName) para ArticleResolver.
Chame o método Create. Para obter mais informações, consulte Definição de um artigo.
Para usar um manipulador de lógica de negócios com um elemento de tabela existente
Crie uma conexão com o Publisher usando a classe ServerConnection.
Crie uma instância da classe MergeArticle.
Defina as propriedades Name, PublicationNamee DatabaseName.
Defina a conexão da etapa 1 para a propriedade ConnectionContext.
Chame o método LoadProperties para obter as propriedades do objeto. Se esse método retornar falso, as propriedades do artigo na etapa 3 foram definidas incorretamente ou o artigo não existe. Para obter mais informações, consulte Exibir e modificar propriedades do artigo.
Defina o nome amigável do manipulador de lógica de negócios para ArticleResolver. Este é o valor da propriedade FriendlyName especificada ao registrar o manipulador de lógica de negócios.
Exemplos (RMO)
Este exemplo é um manipulador de lógica de negócios que registra informações sobre inserções, atualizações e exclusões no Assinante.
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
Este exemplo registra um manipulador de lógica de negócios no Distribuidor.
// 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
Este exemplo altera um artigo existente para usar o manipulador de lógica de negócios.
// 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
Conteúdo relacionado
- Implementar um resolvedor de conflitos personalizado para um artigo de fusão
- Depurar um manipulador de lógica de negócios (programação de replicação)
- Práticas recomendadas de segurança de replicação
- Conceitos de objetos de gerenciamento de replicação