Cómo crear una instantánea para una publicación de mezcla con filtros con parámetros (programación con RMO)

Si desea generar una instantánea para una publicación de mezcla utilizando filtros con parámetros, debe generar primero una instantánea estándar (esquema) que contenga todos los metadatos del suscriptor para la suscripción. A continuación, genere la parte de la instantánea que contiene la partición específica del suscriptor de los datos publicados. Para obtener más información, vea Cómo crear la instantánea inicial (programación con RMO).

Puede utilizar Objetos de administración de replicación (RMO) para generar mediante programación instantáneas con particiones de las maneras siguientes:

  • Permita a los suscriptores que soliciten la generación y aplicación de instantáneas la primera vez que se sincronicen.

  • Genere previamente las instantáneas para cada partición.

  • Genere manualmente una instantánea para cada suscriptor ejecutando el Agente de instantáneas.

Nota

Si al filtrar un artículo se producen particiones no superpuestas que son únicas para cada suscripción (especificando el valor NonOverlappingSingleSubscription para PartitionOption al crear un artículo de mezcla), cada vez que se ejecuta el Agente de mezcla se limpian los metadatos. Esto significa que la instantánea con particiones expira antes. Cuando utilice esta opción, puede ser conveniente permitir a los suscriptores que soliciten la generación de instantáneas. Para obtener más información, vea la sección Usar las opciones de filtrado apropiadas del tema Filtros de fila con parámetros.

Nota de seguridadNota de seguridad

Cuando sea posible, pida a los usuarios que proporcionen credenciales de seguridad en tiempo de ejecución. Si debe almacenar credenciales, use los servicios de cifrado (en inglés) proporcionados por Microsoft Windows .NET Framework.

Para crear una publicación que permita a los suscriptores iniciar la generación y entrega de instantáneas

  1. Cree una conexión al publicador mediante la clase ServerConnection.

  2. Cree una instancia de la clase ReplicationDatabase para la base de datos de publicación, establezca la propiedad ConnectionContext en la instancia de ServerConnection del paso 1 y llame al método LoadProperties. Si LoadProperties devuelve false, confirme que la base de datos existe.

  3. Si la propiedad EnabledMergePublishing está establecida en false, cámbiela a true y llame a CommitPropertyChanges.

  4. Cree una instancia de la clase MergePublication y establezca las propiedades siguientes para este objeto:

    • La ServerConnection del paso 1 para ConnectionContext.

    • El nombre de la base de datos publicada para DatabaseName.

    • Un nombre de publicación para Name.

    • El número máximo de trabajos de instantáneas dinámicas que se van a ejecutar para MaxConcurrentDynamicSnapshots. Dado que las solicitudes de instantáneas iniciadas por el suscriptor pueden producirse en cualquier momento, esta propiedad limita el número de trabajos del Agente de instantáneas que se pueden ejecutar simultáneamente cuando varios suscriptores solicitan al mismo tiempo su instantánea con particiones. Cuando se está ejecutando el número máximo de trabajos, las demás solicitudes de instantáneas con particiones se ponen en la cola hasta que se completa uno de los trabajos en ejecución.

    • Utilice el operador lógico OR bit a bit (| en Visual C# y Or en Visual Basic) para agregar el valor AllowSubscriberInitiatedSnapshot a Attributes.

    • Los campos Login y Password de SnapshotGenerationAgentProcessSecurity para proporcionar las credenciales de la cuenta de Microsoft Windows con la que se ejecuta el trabajo del Agente de mezcla.

      Nota

      Se recomienda establecer SnapshotGenerationAgentProcessSecurity cuando un miembro de la función fija de servidor sysadmin crea la publicación. Para obtener más información, vea Modelo de seguridad del Agente de replicación.

  5. Llame al método Create para crear la publicación.

    Nota de seguridadNota de seguridad

     Cuando se configura un publicador con un distribuidor remoto, los valores suministrados para todas las propiedades, incluidos SnapshotGenerationAgentProcessSecurity, se envían al distribuidor como texto simple. Debe cifrar la conexión entre el publicador y su distribuidor remoto antes de llamar al método Create. Para obtener más información, vea Cifrar conexiones a SQL Server.

  6. Utilice la propiedad MergeArticle para agregar los artículos a la publicación. Especifique la propiedad FilterClause al menos para un artículo que defina el filtro con parámetros. (Opcional) Cree objetos MergeJoinFilter que definan filtros de combinación entre artículos. Para obtener más información, vea Cómo definir un artículo (programación con RMO).

  7. Si el valor de SnapshotAgentExists es false, llame a CreateSnapshotAgent para crear el trabajo inicial de Agente de instantáneas para esta publicación.

  8. Llame al método StartSnapshotGenerationAgentJob del objeto MergePublication creado en el paso 4. Esto inicia el trabajo de agente que genera la instantánea inicial. Para obtener más información sobre cómo generar una instantánea inicial y definir una programación personalizada para el Agente de instantáneas, vea Cómo crear la instantánea inicial (programación con RMO).

  9. (Opcional) Compruebe que hay establecido un valor true en la propiedad SnapshotAvailable para que determine cuándo está lista para usarse la instantánea inicial.

  10. Cuando el Agente de mezcla de un suscriptor se conecta por primera vez, se genera automáticamente una instantánea con particiones.

Para crear una publicación y pregenerar o actualizar automáticamente las instantáneas

  1. Utilice una instancia de la clase MergePublication para definir una publicación de mezcla. Para obtener más información, vea Cómo crear una publicación (programación con RMO).

  2. Utilice la propiedad MergeArticle para agregar artículos a la publicación. Especifique la propiedad FilterClause al menos para un artículo que defina el filtro con parámetros y cree objetos MergeJoinFilter que definan filtros de unión entre artículos. Para obtener más información, vea Cómo definir un artículo (programación con RMO).

  3. Si el valor de SnapshotAgentExists es false, llame a CreateSnapshotAgent para crear el trabajo de Agente de instantáneas para esta publicación.

  4. Llame al método StartSnapshotGenerationAgentJob del objeto MergePublication creado en el paso 1. Este método inicia el trabajo de agente que genera la instantánea inicial. Para obtener más información sobre cómo generar una instantánea inicial y definir una programación personalizada para el Agente de instantáneas, vea Cómo crear la instantánea inicial (programación con RMO).

  5. Compruebe que hay establecido un valor true en la propiedad SnapshotAvailable para que determine cuándo está lista para usarse la instantánea inicial.

  6. Cree una instancia de la clase MergePartition y establezca los criterios de filtro con parámetros para el suscriptor utilizando una o ambas de las propiedades siguientes:

  7. Cree una instancia de la clase MergeDynamicSnapshotJob y establezca la misma propiedad como en el paso 6.

  8. Utilice la clase ReplicationAgentSchedule para definir una programación para generar la instantánea filtrada para la partición del suscriptor.

  9. Utilizando la instancia de MergePublication del paso 1, llame a AddMergePartition. Pase el objeto MergePartition del paso 6.

  10. Utilizando la instancia de MergePublication del paso 1, llame al método AddMergeDynamicSnapshotJob. Pase el objeto MergeDynamicSnapshotJob del paso 7 y el objeto ReplicationAgentSchedule del paso 8.

  11. Llame a EnumMergeDynamicSnapshotJobs y busque el objeto MergeDynamicSnapshotJob para el trabajo de instantánea con particiones recientemente agregado en la matriz devuelta.

  12. Obtenga la propiedad Name de la tarea.

  13. Cree una conexión al Distribuidor mediante la clase ServerConnection.

  14. Cree una instancia de la clase de Objetos de administración de SQL Server (SMO) Server, pasando el objeto ServerConnection del paso 13.

  15. Cree una instancia de la clase Job, pasando la propiedad JobServer del objeto Server del paso 14 y el nombre de trabajo del paso 12.

  16. Llame al método Start para iniciar el trabajo de instantánea con particiones.

  17. Repita los pasos 6-16 para cada suscriptor.

Para crear una publicación y crear manualmente instantáneas para cada partición

  1. Utilice una instancia de la clase MergePublication para definir una publicación de mezcla. Para obtener más información, vea Cómo crear una publicación (programación con RMO).

  2. Utilice la propiedad MergeArticle para agregar artículos a la publicación. Especifique la propiedad FilterClause al menos para un artículo que defina el filtro con parámetros y cree objetos MergeJoinFilter que definan filtros de combinanción entre artículos. Para obtener más información, vea Cómo definir un artículo (programación con RMO).

  3. Genere la instantánea inicial. Para obtener más información, vea Cómo crear la instantánea inicial (programación con RMO).

  4. Cree una instancia de la clase SnapshotGenerationAgent y establezca las propiedades necesarias siguientes:

  5. Establezca el valor Merge para ReplicationType.

  6. Establezca una o más de las propiedades siguientes para definir los parámetros del particionamiento:

  7. Llame al método GenerateSnapshot.

  8. Repita los pasos 4-7 para cada suscriptor.

Ejemplo

En este ejemplo se crea una publicación de mezcla que permite a los suscriptores solicitar la generación de instantáneas.

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

En este ejemplo se crea manualmente la partición del suscriptor y la instantánea filtrada para una publicación de mezcla con filtros de filas con 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

En este ejemplo se inicia manualmente el Agente de instantáneas para generar la instantánea de datos filtrados de un suscriptor para una publicación de mezcla con filtros de filas con 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