Procedura: Creazione di uno snapshot per una pubblicazione di tipo merge con filtri con parametri (programmazione RMO)

Quando si genera uno snapshot per una pubblicazione di tipo merge utilizzando filtri con parametri, è necessario innanzitutto generare uno snapshot standard (schema) che contiene tutti i metadati del Sottoscrittore per la sottoscrizione. Generare quindi la parte dello snapshot che contiene la partizione dei dati pubblicati specifica del Sottoscrittore. Per ulteriori informazioni, vedere Procedura: Creazione dello snapshot iniziale (programmazione RMO).

È possibile utilizzare oggetti RMO (Replication Management Objects) per generare snapshot partizionati a livello di programmazione nelle modalità seguenti:

  • Consentire ai Sottoscrittori di richiedere la generazione e l'applicazione degli snapshot alla prima sincronizzazione.

  • Pregenerare uno snapshot per ogni partizione.

  • Generare manualmente uno snapshot per ogni Sottoscrittore eseguendo l'agente snapshot.

Nota

Quando il filtro di un articolo produce partizioni non sovrapposte univoche per ogni sottoscrizione (specificando un valore NonOverlappingSingleSubscription per PartitionOption nel caso della creazione di un articolo di tipo merge), i metadati vengono puliti ogni volta che viene eseguito l'agente di merge. Lo snapshot partizionato scade quindi più rapidamente. Quando si utilizza questa opzione, è consigliabile consentire ai Sottoscrittori di richiedere la generazione degli snapshot. Per ulteriori informazioni, vedere la sezione relativa all'utilizzo delle opzioni di filtro appropriate nell'argomento Filtri di riga con parametri.

Nota sulla sicurezzaNota sulla sicurezza

Se possibile, richiedere agli utenti di immettere le credenziali di protezione in fase di esecuzione. Se è necessario archiviare le credenziali, utilizzare i servizi di crittografia offerti da Microsoft Windows .NET Framework.

Per creare una pubblicazione che consente ai Sottoscrittori di avviare la generazione e il recapito di snapshot

  1. Creare una connessione al server di pubblicazione tramite la classe ServerConnection.

  2. Creare un'istanza della classe ReplicationDatabase per il database di pubblicazione, impostare la proprietà ConnectionContext sull'istanza di ServerConnection indicata nel passaggio 1, quindi chiamare il metodo LoadProperties. Se LoadProperties restituisce false, verificare che il database esista.

  3. Se la proprietà EnabledMergePublishing è false, impostarla su true e chiamare CommitPropertyChanges.

  4. Creare un'istanza della classe MergePublication e impostare le proprietà seguenti per questo oggetto:

    • Oggetto ServerConnection indicato nel passaggio 1 per ConnectionContext.

    • Nome del database di pubblicazione per DatabaseName.

    • Nome per la pubblicazione per Name.

    • Numero massimo di processi di snapshot dinamici da eseguire per MaxConcurrentDynamicSnapshots. Poiché le richieste di snapshot avviate dal Sottoscrittore possono verificarsi in qualsiasi momento, questa proprietà limita il numero di processi dell'agente snapshot che possono essere eseguiti simultaneamente quando più Sottoscrittori richiedono il rispettivo snapshot partizionato contemporaneamente. Quando è in esecuzione il numero massimo di processi, le richieste aggiuntive di snapshot partizionati vengono inserite nella coda fino al completamento di uno dei processi.

    • Utilizzare l'operatore logico OR bit per bit (| in Visual C# e Or in Visual Basic) per aggiungere il valore AllowSubscriberInitiatedSnapshot a Attributes.

    • Campi Login e Password di SnapshotGenerationAgentProcessSecurity per fornire le credenziali per l'account di Microsoft Windows con cui verrà eseguito il processo dell'agente snapshot.

      Nota

      È consigliabile impostare SnapshotGenerationAgentProcessSecurity quando la pubblicazione viene creata da un membro del ruolo predefinito del server sysadmin. Per ulteriori informazioni, vedere Modello di sicurezza dell'agente di replica.

  5. Chiamare il metodo Create per creare la pubblicazione.

    Nota sulla sicurezzaNota sulla sicurezza

     Quando si configura un server di pubblicazione con un server di distribuzione remoto, i valori specificati per tutte le proprietà, inclusa SnapshotGenerationAgentProcessSecurity, vengono inviati al server di distribuzione come testo normale. È consigliabile crittografare la connessione tra il server di pubblicazione e il server di distribuzione remoto prima di chiamare il metodo Create. Per ulteriori informazioni, vedere Crittografia delle connessioni a SQL Server.

  6. Utilizzare la proprietà MergeArticle per aggiungere articoli alla pubblicazione. Specificare la proprietà FilterClause per almeno un articolo che definisce il filtro con parametri. (Facoltativo) Creare oggetti MergeJoinFilter che definiscono i filtri join tra gli articoli. Per ulteriori informazioni, vedere Procedura: Definizione di un articolo (programmazione RMO).

  7. Se il valore di SnapshotAgentExists è false, chiamare CreateSnapshotAgent per creare il processo dell'agente snapshot iniziale per questa pubblicazione.

  8. Chiamare il metodo StartSnapshotGenerationAgentJob dell'oggetto MergePublication creato nel passaggio 4. In questo modo viene avviato il processo dell'agente che genera lo snapshot iniziale. Per ulteriori informazioni sulla generazione di uno snapshot iniziale e sulla definizione di una pianificazione personalizzata per l'agente snapshot, vedere Procedura: Creazione dello snapshot iniziale (programmazione RMO).

  9. (Facoltativo) Verificare la presenza di un valore true per la proprietà SnapshotAvailable per determinare quando lo snapshot iniziale è pronto per l'utilizzo.

  10. La prima volta che l'agente di merge per un Sottoscrittore si connette, verrà generato automaticamente uno snapshot partizionato.

Per creare una pubblicazione e pregenerare o aggiornare automaticamente gli snapshot

  1. Utilizzare un'istanza della classe MergePublication per definire una pubblicazione di tipo merge. Per ulteriori informazioni, vedere Procedura: Creazione di una pubblicazione (programmazione RMO).

  2. Utilizzare la proprietà MergeArticle per aggiungere articoli alla pubblicazione. Specificare la proprietà FilterClause per almeno un articolo che definisce il filtro con parametri, quindi creare eventuali oggetti MergeJoinFilter che definiscono filtri join tra gli articoli. Per ulteriori informazioni, vedere Procedura: Definizione di un articolo (programmazione RMO).

  3. Se il valore di SnapshotAgentExists è false, chiamare CreateSnapshotAgent per creare il processo dell'agente snapshot per questa pubblicazione.

  4. Chiamare il metodo StartSnapshotGenerationAgentJob dell'oggetto MergePublication creato nel passaggio 1. Questo metodo avvia il processo dell'agente che genera lo snapshot iniziale. Per ulteriori informazioni sulla generazione di uno snapshot iniziale e sulla definizione di una pianificazione personalizzata per l'agente snapshot, vedere Procedura: Creazione dello snapshot iniziale (programmazione RMO).

  5. (Facoltativo) Verificare la presenza di un valore true per la proprietà SnapshotAvailable per determinare quando lo snapshot iniziale è pronto per l'utilizzo.

  6. Creare un'istanza della classe MergePartition e impostare i criteri di filtro con parametri per il Sottoscrittore utilizzando una o entrambe le proprietà seguenti:

  7. Creare un'istanza della classe MergeDynamicSnapshotJob e impostare la stessa proprietà indicata nel passaggio 6.

  8. Utilizzare la classe ReplicationAgentSchedule per definire una pianificazione per la generazione dello snapshot filtrato per la partizione del Sottoscrittore.

  9. Utilizzando l'istanza di MergePublication indicata nel passaggio 1, chiamare AddMergePartition. Passare l'oggetto MergePartition indicato nel passaggio 6.

  10. Utilizzando l'istanza di MergePublication indicata nel passaggio 1, chiamare il metodo AddMergeDynamicSnapshotJob. Passare l'oggetto MergeDynamicSnapshotJob indicato nel passaggio 7 e l'oggetto ReplicationAgentSchedule indicato nel passaggio 8.

  11. Chiamare EnumMergeDynamicSnapshotJobs e individuare l'oggetto MergeDynamicSnapshotJob per il processo di snapshot partizionato appena aggiunto nella matrice restituita.

  12. Ottenere la proprietà Name per il processo.

  13. Creare una connessione al server di distribuzione tramite la classe ServerConnection.

  14. Creare un'istanza della classe Server SMO (SQL Server Management Objects) passando l'oggetto ServerConnection indicato nel passaggio 13.

  15. Creare un'istanza della classe Job passando la proprietà JobServer dell'oggetto Server indicato nel passaggio 14 e il nome del processo indicato nel passaggio 12.

  16. Chiamare il metodo Start per avviare il processo di snapshot partizionato.

  17. Ripetere i passaggi da 6 a 16 per ogni Sottoscrittore.

Per creare una pubblicazione e creare manualmente gli snapshot per ogni partizione

  1. Utilizzare un'istanza della classe MergePublication per definire una pubblicazione di tipo merge. Per ulteriori informazioni, vedere Procedura: Creazione di una pubblicazione (programmazione RMO).

  2. Utilizzare la proprietà MergeArticle per aggiungere articoli alla pubblicazione. Specificare la proprietà FilterClause per almeno un articolo che definisce il filtro con parametri, quindi creare eventuali oggetti MergeJoinFilter che definiscono i filtri join tra gli articoli. Per ulteriori informazioni, vedere Procedura: Definizione di un articolo (programmazione RMO).

  3. Generare lo snapshot iniziale. Per ulteriori informazioni, vedere Procedura: Creazione dello snapshot iniziale (programmazione RMO).

  4. Creare un'istanza della classe SnapshotGenerationAgent e impostare le seguenti proprietà obbligatorie:

  5. Impostare un valore di Merge per ReplicationType.

  6. Impostare una o più delle seguenti proprietà per definire i parametri di partizionamento:

  7. Chiamare il metodo GenerateSnapshot.

  8. Ripetere i passaggi da 4 a 7 per ogni Sottoscrittore.

Esempio

In questo esempio viene creata una pubblicazione di tipo merge che consente ai Sottoscrittori di richiedere la generazione di snapshot.

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

In questo esempio vengono creati manualmente la partizione del Sottoscrittore e lo snapshot filtrato per una pubblicazione di tipo merge con filtri di riga con parametri.

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

In questo esempio viene avviato manualmente l'agente snapshot per generare lo snapshot di dati filtrati per un Sottoscrittore in una pubblicazione di tipo merge con filtri di riga con parametri.

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