Como criar um instantâneo para uma publicação de mesclagem com filtros com parâmetros (Programação RMO)

Ao gerar um instantâneo para uma publicação de mesclagem usando filtros com parâmetros, deve-se, em primeiro lugar, gerar um instantâneo (de esquema) padrão, que contenha todos os metadados do Assinante para a assinatura. Em seguida, gera-se a parte do instantâneo que contém a partição específica do Assinante dos dados publicados. Para obter mais informações, consulte Como criar o instantâneo inicial (Programação RMO).

Você pode usar RMO (Replication Management Objects) para gerar instantâneos particionados programaticamente dos seguintes modos:

  • Permita que os Assinantes solicitem geração e aplicação de instantâneos na primeira vez que eles sincronizarem.

  • Gere previamente instantâneos para cada partição.

  • Gere manualmente um instantâneo para cada Assinante executando o Snapshot Agent.

ObservaçãoObservação

Quando a filtragem de um artigo gerar partições não sobrepostas, exclusivas de cada assinatura (especificando um valor de NonOverlappingSingleSubscription para PartitionOption ao criar um artigo de mesclagem), metadados são limpos sempre que o Merge Agent for executado. Isso significa que o instantâneo particionado irá expirar mais rapidamente. Ao usar essa opção, considere permitir que os Assinantes solicitem geração do instantâneo. Para obter mais informações, consulte a seção "Usando as opções de filtragem” apropriadas no tópico Filtro de linha com parâmetros.

Observação sobre segurançaObservação sobre segurança

Quando possível, solicite que os usuários insiram as credenciais de segurança em tempo de execução. Se for preciso armazenar credenciais, use os serviços criptográficos fornecidos pelo Microsoft .NET Framework do Windows.

Para criar uma publicação que permita que os Assinantes inicializem geração e entrega de instantâneo

  1. Crie uma conexão com o Publicador usando a classe ServerConnection.

  2. Crie uma instância da classe ReplicationDatabase para o banco de dados de publicação; defina a propriedade ConnectionContext para a instância de ServerConnection da etapa 1 e chame o método LoadProperties. Se LoadProperties retornar false, confirme a existência do banco de dados.

  3. Se a propriedade EnabledMergePublishing for false, defina-a como true e chame CommitPropertyChanges.

  4. Crie uma instância da classe MergePublication e defina as propriedades a seguir para esse objeto:

    • O ServerConnection da etapa 1 para ConnectionContext.

    • Nome do banco de dados publicado para DatabaseName.

    • Um nome para a publicação para Name.

    • O número máximo de trabalhos de instantâneo dinâmicos a serem executados para MaxConcurrentDynamicSnapshots. Uma vez que solicitações de instantâneo iniciado pelo Assinante podem ocorrer a qualquer momento, essa propriedade limita o número de trabalhos do Snapshot Agent que podem ser executados simultaneamente quando vários Assinantes solicitam seu instantâneo particionado ao mesmo tempo. Quando o número máximo de trabalhos estiver sendo executado, solicitações de instantâneos particionados adicionais são enfileiradas até que um dos trabalhos que está sendo executado seja concluído.

    • Use o operador lógico bit a bit OR (| em Visual C# e Or em Visual Basic) para adicionar o valor AllowSubscriberInitiatedSnapshot a Attributes.

    • Os campos Login e Password de SnapshotGenerationAgentProcessSecurity para fornecer as credenciais para a conta do Windows Microsoft em que o Snapshot Agent é executado.

      ObservaçãoObservação

      Recomenda-se definir SnapshotGenerationAgentProcessSecurity quando a publicação é criada por um membro da função de servidor fixa sysadmin. Para obter mais informações, consulte Modelo de segurança do agente de replicação.

  5. Chame o método Create para criar a publicação.

    Observação sobre segurançaObservação sobre segurança

     Quando um Publicador é configurado com um Distribuidor remoto, os valores fornecidos para todas as propriedades, inclusive SnapshotGenerationAgentProcessSecurity, são enviados ao Distribuidor como texto sem formatação. É necessário criptografar a conexão entre o Publicador e seu Distribuidor remoto antes de chamar o método Create. Para obter mais informações, consulte Criptografando conexões com o SQL Server.

  6. Use a propriedade MergeArticle para adicionar artigos à publicação. Especifique a propriedade FilterClause para pelo menos um artigo que defina o filtro com parâmetros. (Opcional) Crie objetos MergeJoinFilter que definam filtros de junção entre artigos. Para obter mais informações, consulte Como definir um Artigo (programação RMO).

  7. Se o valor de SnapshotAgentExists for false, chame CreateSnapshotAgent para criar o trabalho inicial do Snapshot Agent para essa publicação.

  8. Chame o método StartSnapshotGenerationAgentJob de objeto MergePublication criado na etapa 4. Isso inicia o trabalho do agente que gera o instantâneo inicial. Para obter mais informações sobre como gerar um instantâneo inicial e definir um agendamento personalizado para o Snapshot Agent, consulte Como criar o instantâneo inicial (Programação RMO).

  9. (Opcional) Procure um valor de true para a propriedade SnapshotAvailable a fim de determinar quando o instantâneo inicial está pronto para ser usado.

  10. Quando o Merge Agent para um Assinante for conectado pela primeira vez, um instantâneo particionado é gerado automaticamente.

Para criar uma publicação e gerar previamente ou atualizar automaticamente instantâneos

  1. Use uma instância da classe MergePublication para definir uma publicação de mesclagem. Para obter mais informações, consulte Como criar uma publicação (programação RMO).

  2. Use a propriedade MergeArticle para adicionar artigos à publicação. Especifique a propriedade FilterClause para pelo menos um artigo que defina o filtro com parâmetros e crie quaisquer objetos MergeJoinFilter que definam filtros de junção entre artigos. Para obter mais informações, consulte Como definir um Artigo (programação RMO).

  3. Se o valor de SnapshotAgentExists for false, chame CreateSnapshotAgent para criar o trabalho do snapshot agent para essa publicação.

  4. Chame o método StartSnapshotGenerationAgentJob do objeto MergePublication criado na etapa 1. Esse método inicia o trabalho do agente que gera o instantâneo inicial. Para obter mais informações sobre como gerar um instantâneo inicial e definir um agendamento personalizado para o Snapshot Agent, consulte Como criar o instantâneo inicial (Programação RMO).

  5. (Opcional) Procure um valor de true para a propriedade SnapshotAvailable a fim de determinar quando o instantâneo inicial está pronto para ser usado.

  6. Crie uma instância da classe MergePartitione defina os critérios de filtragem com parâmetros para o Assinante, usando uma ou mais das seguintes propriedades:

  7. Crie uma instância da classe MergeDynamicSnapshotJob e defina a mesma propriedade que a da etapa 6.

  8. Use a classe ReplicationAgentSchedule para definir uma agenda para gerar o instantâneo filtrado para a partição de Assinante.

  9. Usando a instância de MergePublication da etapa 1, chame AddMergePartition. Passe o objeto MergePartition da etapa 6.

  10. Usando a instância de MergePublication da etapa 1, chame o método AddMergeDynamicSnapshotJob. Passe o objeto MergeDynamicSnapshotJob da etapa 7 e o objeto ReplicationAgentSchedule da etapa 8.

  11. Chame EnumMergeDynamicSnapshotJobs e localize o objeto MergeDynamicSnapshotJob para o trabalho de instantâneo particionado recém-adicionado à matriz retornada.

  12. Adquira a propriedade Name para o trabalho.

  13. Crie uma conexão com o Distribuidor usando a classe ServerConnection.

  14. Crie uma instância da classe Server do SQL Server Management Objetcs (SMO), passando o objeto ServerConnection da etapa 13.

  15. Crie uma instância da classe Job passando a propriedade JobServerdo objeto Server da etapa 14 e o nome do trabalho da etapa 12.

  16. Chame o método Start para iniciar o trabalho de instantâneo particionado.

  17. Repita as etapas 6-16 para cada Assinante.

Para criar uma publicação e criar manualmente instantâneos para cada partição

  1. Use uma instância da classe MergePublication para definir uma publicação de mesclagem. Para obter mais informações, consulte Como criar uma publicação (programação RMO).

  2. Use a propriedade MergeArticle para adicionar artigos para a publicação. Especifique a propriedade FilterClause para pelo menos um artigo que defina o filtro com parâmetros e crie quaisquer objetos MergeJoinFilter que definam filtros de junção entre artigos. Para obter mais informações, consulte Como definir um Artigo (programação RMO).

  3. Gere o instantâneo inicial. Para obter mais informações, consulte Como criar o instantâneo inicial (Programação RMO).

  4. Crie uma instância de classe SnapshotGenerationAgent e defina as seguintes propriedades necessárias:

  5. Defina um valor de Merge para ReplicationType.

  6. Defina uma ou mais das seguintes propriedades a fim de definir os parâmetros de particionamento:

  7. Chame o método GenerateSnapshot.

  8. Repita as etapas 4-7 para cada Assinante.

Exemplo

Esse exemplo cria uma publicação de mesclagem que permite aos Assinantes solicitar geração de instantâneo.

            // Set the Publisher, publication database, and publication names.
            string publisherName = publisherInstance;
            string publicationName = "AdvWorksSalesOrdersMerge";
            string publicationDbName = "AdventureWorks2008R2";

            ReplicationDatabase publicationDb;
            MergePublication publication;

            // Create a connection to the Publisher.
            ServerConnection conn = new ServerConnection(publisherName);

            try
            {
                // Connect to the Publisher.
                conn.Connect();

                // Enable the database for merge publication.               
                publicationDb = new ReplicationDatabase(publicationDbName, conn);
                if (publicationDb.LoadProperties())
                {
                    if (!publicationDb.EnabledMergePublishing)
                    {
                        publicationDb.EnabledMergePublishing = true;
                    }
                }
                else
                {
                    // Do something here if the database does not exist. 
                    throw new ApplicationException(String.Format(
                        "The {0} database does not exist on {1}.",
                        publicationDb, publisherName));
                }

                // Set the required properties for the merge publication.
                publication = new MergePublication();
                publication.ConnectionContext = conn;
                publication.Name = publicationName;
                publication.DatabaseName = publicationDbName;

                // Enable precomputed partitions.
                publication.PartitionGroupsOption = PartitionGroupsOption.True;

                // Specify the Windows account under which the Snapshot Agent job runs.
                // This account will be used for the local connection to the 
                // Distributor and all agent connections that use Windows Authentication.
                publication.SnapshotGenerationAgentProcessSecurity.Login = winLogin;
                publication.SnapshotGenerationAgentProcessSecurity.Password = winPassword;

                // Explicitly set the security mode for the Publisher connection
                // Windows Authentication (the default).
                publication.SnapshotGenerationAgentPublisherSecurity.WindowsAuthentication = true;

                // Enable Subscribers to request snapshot generation and filtering.
                publication.Attributes |= PublicationAttributes.AllowSubscriberInitiatedSnapshot;
                publication.Attributes |= PublicationAttributes.DynamicFilters;

                // Enable pull and push subscriptions.
                publication.Attributes |= PublicationAttributes.AllowPull;
                publication.Attributes |= PublicationAttributes.AllowPush;

                if (!publication.IsExistingObject)
                {
                    // Create the merge publication.
                    publication.Create();
                    
                    // Create a Snapshot Agent job for the publication.
                    publication.CreateSnapshotAgent();
                }
                else
                {
                    throw new ApplicationException(String.Format(
                        "The {0} publication already exists.", publicationName));
                }
            }

            catch (Exception ex)
            {
                // Implement custom application error handling here.
                throw new ApplicationException(String.Format(
                    "The publication {0} could not be created.", publicationName), ex);
            }
            finally
            {
                conn.Disconnect();
            }
' Set the Publisher, publication database, and publication names.
Dim publisherName As String = publisherInstance
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2008R2"

Dim publicationDb As ReplicationDatabase
Dim publication As MergePublication

' Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Enable the database for merge publication.                
    publicationDb = New ReplicationDatabase(publicationDbName, conn)
    If publicationDb.LoadProperties() Then
        If Not publicationDb.EnabledMergePublishing Then
            publicationDb.EnabledMergePublishing = True
        End If
    Else
        ' Do something here if the database does not exist. 
        Throw New ApplicationException(String.Format( _
         "The {0} database does not exist on {1}.", _
         publicationDb, publisherName))
    End If

    ' Set the required properties for the merge publication.
    publication = New MergePublication()
    publication.ConnectionContext = conn
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName

    ' Enable precomputed partitions.
    publication.PartitionGroupsOption = PartitionGroupsOption.True

    ' Specify the Windows account under which the Snapshot Agent job runs.
    ' This account will be used for the local connection to the 
    ' Distributor and all agent connections that use Windows Authentication.
    publication.SnapshotGenerationAgentProcessSecurity.Login = winLogin
    publication.SnapshotGenerationAgentProcessSecurity.Password = winPassword

    ' Explicitly set the security mode for the Publisher connection
    ' Windows Authentication (the default).
    publication.SnapshotGenerationAgentPublisherSecurity.WindowsAuthentication = True

    ' Enable Subscribers to request snapshot generation and filtering.
    publication.Attributes = publication.Attributes Or _
        PublicationAttributes.AllowSubscriberInitiatedSnapshot
    publication.Attributes = publication.Attributes Or _
        PublicationAttributes.DynamicFilters

    ' Enable pull and push subscriptions
    publication.Attributes = publication.Attributes Or _
        PublicationAttributes.AllowPull
    publication.Attributes = publication.Attributes Or _
        PublicationAttributes.AllowPush

    If Not publication.IsExistingObject Then
        ' Create the merge publication.
        publication.Create()

        ' Create a Snapshot Agent job for the publication.
        publication.CreateSnapshotAgent()
    Else
        Throw New ApplicationException(String.Format( _
            "The {0} publication already exists.", publicationName))
    End If
Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
        "The publication {0} could not be created.", publicationName), ex)
Finally
    conn.Disconnect()
End Try

Esse exemplo cria a partição de Assinante e o instantâneo filtrado manualmente para uma publicação de mesclagem com filtros de linha com parâmetros.

            // Define the server, database, and publication names
            string publisherName = publisherInstance;
            string publicationName = "AdvWorksSalesOrdersMerge";
            string publicationDbName = "AdventureWorks2008R2";
            string distributorName = publisherInstance;

            MergePublication publication;
            MergePartition partition;
            MergeDynamicSnapshotJob snapshotAgentJob;
            ReplicationAgentSchedule schedule;
            
            // Create a connection to the Publisher.
            ServerConnection publisherConn = new ServerConnection(publisherName);

            // Create a connection to the Distributor to start the Snapshot Agent.
            ServerConnection distributorConn = new ServerConnection(distributorName);

            try
            {
                // Connect to the Publisher.
                publisherConn.Connect();

                // Set the required properties for the publication.
                publication = new MergePublication();
                publication.ConnectionContext = publisherConn;
                publication.Name = publicationName;
                publication.DatabaseName = publicationDbName;


                // If we can't get the properties for this merge publication, 
                // then throw an application exception.
                if (publication.LoadProperties() || publication.SnapshotAvailable)
                {
                    // Set a weekly schedule for the filtered data snapshot.
                    schedule = new ReplicationAgentSchedule();
                    schedule.FrequencyType = ScheduleFrequencyType.Weekly;
                    schedule.FrequencyRecurrenceFactor = 1;
                    schedule.FrequencyInterval = Convert.ToInt32(0x001);

                    // Set the value of Hostname that defines the data partition. 
                    partition = new MergePartition();
                    partition.DynamicFilterHostName = hostname;
                    snapshotAgentJob = new MergeDynamicSnapshotJob();
                    snapshotAgentJob.DynamicFilterHostName = hostname;

                    // Create the partition for the publication with the defined schedule.
                    publication.AddMergePartition(partition);
                    publication.AddMergeDynamicSnapshotJob(snapshotAgentJob, schedule);
                }
                else
                {
                    throw new ApplicationException(String.Format(
                        "Settings could not be retrieved for the publication, " +
                        " or the initial snapshot has not been generated. " +
                        "Ensure that the publication {0} exists on {1} and " +
                        "that the Snapshot Agent has run successfully.",
                        publicationName, publisherName));
                }
            }
            catch (Exception ex)
            {
                // Do error handling here.
                throw new ApplicationException(string.Format(
                    "The partition for '{0}' in the {1} publication could not be created.",
                    hostname, publicationName), ex);
            }
            finally
            {
                publisherConn.Disconnect();
                if (distributorConn.IsOpen) distributorConn.Disconnect();
            }
' Define the server, database, and publication names
Dim publisherName As String = publisherInstance
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2008R2"
Dim distributorName As String = publisherInstance

Dim publication As MergePublication
Dim partition As MergePartition
Dim snapshotAgentJob As MergeDynamicSnapshotJob
Dim schedule As ReplicationAgentSchedule

' Create a connection to the Publisher.
Dim publisherConn As ServerConnection = New ServerConnection(publisherName)

' Create a connection to the Distributor to start the Snapshot Agent.
Dim distributorConn As ServerConnection = New ServerConnection(distributorName)

Try
    ' Connect to the Publisher.
    publisherConn.Connect()

    ' Set the required properties for the publication.
    publication = New MergePublication()
    publication.ConnectionContext = publisherConn
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName


    ' If we can't get the properties for this merge publication, 
    ' then throw an application exception.
    If (publication.LoadProperties() Or publication.SnapshotAvailable) Then
        ' Set a weekly schedule for the filtered data snapshot.
        schedule = New ReplicationAgentSchedule()
        schedule.FrequencyType = ScheduleFrequencyType.Weekly
        schedule.FrequencyRecurrenceFactor = 1
        schedule.FrequencyInterval = Convert.ToInt32("0x001", 16)

        ' Set the value of Hostname that defines the data partition. 
        partition = New MergePartition()
        partition.DynamicFilterHostName = hostname
        snapshotAgentJob = New MergeDynamicSnapshotJob()
        snapshotAgentJob.DynamicFilterHostName = hostname

        ' Create the partition for the publication with the defined schedule.
        publication.AddMergePartition(partition)
        publication.AddMergeDynamicSnapshotJob(snapshotAgentJob, schedule)
    Else
        Throw New ApplicationException(String.Format( _
         "Settings could not be retrieved for the publication, " + _
         " or the initial snapshot has not been generated. " + _
         "Ensure that the publication {0} exists on {1} and " + _
         "that the Snapshot Agent has run successfully.", _
         publicationName, publisherName))
    End If
Catch ex As Exception
    ' Do error handling here.
    Throw New ApplicationException(String.Format( _
     "The partition for '{0}' in the {1} publication could not be created.", _
     hostname, publicationName), ex)
Finally
    publisherConn.Disconnect()
    If distributorConn.IsOpen Then
        distributorConn.Disconnect()
    End If
End Try

Esse exemplo inicia manualmente o Snapshot Agent para a geração do instantâneo de dados filtrado para um Assinante para uma publicação de mesclagem com filtros de linha com parâmetros.

            // Set the Publisher, publication database, and publication names.
            string publicationName = "AdvWorksSalesOrdersMerge";
            string publicationDbName = "AdventureWorks2008R2";
            string publisherName = publisherInstance;
            string distributorName = publisherInstance;

            SnapshotGenerationAgent agent;

            try
            {
                // Set the required properties for Snapshot Agent.
                agent = new SnapshotGenerationAgent();
                agent.Distributor = distributorName;
                agent.DistributorSecurityMode = SecurityMode.Integrated;
                agent.Publisher = publisherName;
                agent.PublisherSecurityMode = SecurityMode.Integrated;
                agent.Publication = publicationName;
                agent.PublisherDatabase = publicationDbName;
                agent.ReplicationType = ReplicationType.Merge;

                // Specify the partition information to generate a 
                // filtered snapshot based on Hostname.
                agent.DynamicFilterHostName = hostname;

                // Start the agent synchronously.
                agent.GenerateSnapshot();
            }
            catch (Exception ex)
            {
                // Implement custom application error handling here.
                throw new ApplicationException(String.Format(
                    "A snapshot could not be generated for the {0} publication."
                    , publicationName), ex);
            }
' Set the Publisher, publication database, and publication names.
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publicationDbName As String = "AdventureWorks2008R2"
Dim publisherName As String = publisherInstance
Dim distributorName As String = publisherInstance

Dim agent As SnapshotGenerationAgent

Try
    ' Set the required properties for Snapshot Agent.
    agent = New SnapshotGenerationAgent()
    agent.Distributor = distributorName
    agent.DistributorSecurityMode = SecurityMode.Integrated
    agent.Publisher = publisherName
    agent.PublisherSecurityMode = SecurityMode.Integrated
    agent.Publication = publicationName
    agent.PublisherDatabase = publicationDbName
    agent.ReplicationType = ReplicationType.Merge

    ' Specify the partition information to generate a 
    ' filtered snapshot based on Hostname.
    agent.DynamicFilterHostName = hostname

    ' Start the agent synchronously.
    agent.GenerateSnapshot()
Catch ex As Exception
    ' Implement custom application error handling here.
    Throw New ApplicationException(String.Format( _
     "A snapshot could not be generated for the {0} publication." _
     , publicationName), ex)
End Try