Share via


Procédure : approvisionner une base de données serveur pour la synchronisation collaborative (non-SQL Server)

Notes

Les rubriques de cette section de la documentation, Synchronisation d'autre bases de données compatibles ADO.NET, montrent comment les bases de données autres que SQL Server peuvent être synchronisées à l'aide de Sync Framework. Dans cette version, SQL Server est utilisé dans les exemples de code, mais le code peut être utilisé pour d'autres bases de données compatibles ADO.NET, en apportant certaines modifications aux objets SQL Server (tels que SqlConnection) et aux requêtes SQL présentées. Pour plus d'informations sur la synchronisation SQL Server, consultez Procédure : configurer et exécuter la synchronisation de bases de données (SQL Server).

Cette rubrique montre comment approvisionner une base de données synchronisée par DbSyncProvider, afin que les modifications de données incrémentielles puissent être suivies dans cette base de données. Les modifications sont suivies de façon à pouvoir être appliquées à d'autres nœuds pendant une session de synchronisation. L'approvisionnement d'une base de données pour Sync Framework passe par les étapes suivantes :

  1. Activer le niveau d'isolement d'instantané pour la base de données

  2. Identifier les tables à synchroniser

  3. Créer des tables de suivi pour stocker des métadonnées par table (et créer des index sur ces tables)

  4. Créer des déclencheurs sur chaque table de base pour remplir et mettre à jour les tables de suivi

  5. (Facultatif) Gérer les données existantes dans la base de données

  6. Créer une table de suivi pour stocker des métadonnées par étendue (et créer un index sur cette table)

  7. Définir les étendues à synchroniser et ainsi spécifier les tables à synchroniser en tant qu'unité

  8. Créer les procédures stockées permettant de sélectionner et mettre à jour les données et les métadonnées

Ces étapes ne sont pas obligatoires pour les bases de données synchronisées par SqlCeSyncProvider ; l'approvisionnement est géré par Sync Framework lorsque la base de données est initialisée.

Une fois approvisionnée, une base de données peut être synchronisée avec d'autres nœuds. Pour plus d'informations sur la façon de configurer et d'exécuter la synchronisation, consultez Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server).

Activer le niveau d'isolement d'instantané pour la base de données

Pendant la phase d'énumération des modifications d'une session de synchronisation, Sync Framework démarre des transactions avec le niveau d'isolement d'instantané. Pour démarrer des transactions avec le niveau d'isolement d'instantané, vous devez affecter à l'option de base de données ALLOW_SNAPSHOT_ISOLATION la valeur ON, comme le montre l'exemple de code suivant :

ALTER DATABASE [database name] SET ALLOW_SNAPSHOT_ISOLATION ON

Pour plus d'informations, consultez la documentation en ligne de SQL Server.

Identifier les tables à synchroniser

La première étape d'approvisionnement de la base de données consiste à identifier les tables à synchroniser. Chaque table doit avoir une clé primaire. Prenons l'exemple du code suivant. Il affiche le schéma de table Sales.Customer dans la base de données SyncSamplesDb_Peer1.

CREATE TABLE Sales.Customer(
    CustomerId uniqueidentifier NOT NULL PRIMARY KEY DEFAULT NEWID(), 
    CustomerName nvarchar(100) NOT NULL,
    SalesPerson nvarchar(100) NOT NULL,
    CustomerType nvarchar(100) NOT NULL)

Un objet DbSyncAdapter est associé à chaque table que vous synchronisez et vous spécifiez la clé primaire dans la collection RowIdColumns de cet objet. Pour plus d'informations, consultez Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server).

Les tables peuvent être vides ou contenir des données existantes. Si la table contient des lignes existantes de données qui doivent être synchronisées, vous devez veiller à ce que chaque ligne soit assortie d'une entrée de métadonnées dans la table de suivi des modifications appropriée. Pour plus d'informations, consultez Gérer les données existantes dans la base de données.

Créer des tables de suivi pour les métadonnées par table

Sync Framework doit disposer d'un moyen de suivre les lignes qui ont été modifiées depuis la session de synchronisation précédente entre deux nœuds. Les modifications sont représentées par deux types différents de métadonnées :

  • les métadonnées par table, qui effectuent le suivi des insertions, mises à jour et suppressions pour chaque table synchronisée ;

  • les métadonnées par étendue, qui effectuent le suivi des modifications que chaque nœud a reçues de l'autre.

Le suivi des métadonnées par table est effectué à l'aide d'une table de suivi pour chaque table de base. La table de base et les tables de suivi doivent être présentes dans chaque base de données synchronisée par DbSyncProvider. La clé primaire de la table de suivi est la même que celle de la table de base, et des colonnes supplémentaires sont requises. Ces colonnes sont décrites dans le tableau suivant. Les noms des colonnes supplémentaires n'ont pas à être identiques à ceux répertoriés, mais ils doivent correspondre, en ordre et en type, aux requêtes ou procédures qui accèdent aux tables de suivi. Certaines de ces procédures sont incluses dans Créer les procédures stockées permettant de sélectionner et mettre à jour les données et les métadonnées.

Colonne

Description

Mise à jour lorsque…

<Clé primaire (PK) de la table de base> - incluez une colonne pour chaque colonne PK.

Colonnes de clé primaire de la table de base.

Une ligne est insérée dans la table de base. L'insertion peut provenir du nœud local ou distant.

update_scope_local_id

ID de l'étendue qui a effectué la dernière mise à jour ou suppression. Pour les mises à jour ou suppressions qui proviennent du nœud local, cette colonne a la valeur NULL.

Fait référence à la colonne scope_local_id de la table d'informations d'étendue. Pour plus d'informations, consultez « Créer des tables de suivi pour les métadonnées par étendue ».

Une mise à jour ou une suppression provenant d'un nœud distant est appliquée à la table de base.

scope_update_peer_key

Identité du nœud qui a effectué la dernière mise à jour ou suppression.

Une mise à jour ou une suppression provenant d'un nœud distant est appliquée à la table de base.

scope_update_peer_timestamp

Valeur d'horodatage au niveau de la base de données distante lorsque la ligne a initialement été mise à jour ou supprimée.

Une mise à jour ou une suppression provenant d'un nœud distant est appliquée à la table de base.

local_update_peer_key

Identité du nœud local. Cette colonne contiendra la valeur 0 pour chaque ligne, sauf si la base de données locale a été restaurée à partir d'une sauvegarde. 1

Une mise à jour ou suppression provenant d'une opération locale ou d'un nœud distant est appliquée à la table de base.

local_update_peer_timestamp

Valeur d'horodatage au niveau de la base de données locale lorsque la ligne a été mise à jour ou supprimée dans la base de données locale. 1

Une mise à jour ou suppression provenant d'une opération locale ou d'un nœud distant est appliquée à la table de base.

create_scope_local_id

Identité de l'étendue qui a effectué l'insertion. Pour les mises à jour ou suppressions qui proviennent du nœud local, cette colonne a la valeur NULL.

Fait référence à la colonne scope_local_id de la table d'informations d'étendue. Pour plus d'informations, consultez « Créer des tables de suivi pour les métadonnées par étendue » dans Procédure : approvisionner une base de données serveur pour la synchronisation collaborative (non-SQL Server).

Une insertion provenant d'un nœud distant est appliquée à la table de base.

scope_create_peer_key

Identité du nœud qui a effectué l'insertion.

Une insertion provenant d'un nœud distant est appliquée à la table de base.

scope_create_peer_timestamp

Valeur d'horodatage au niveau de la base de données distante lorsque la ligne a été initialement insérée.

Une insertion provenant d'un nœud distant est appliquée à la table de base.

local_create_peer_key

Identité du nœud local. Cette colonne contiendra la valeur 0 pour chaque ligne, sauf si la base de données locale a été restaurée à partir d'une sauvegarde. 1

Une insertion provenant d'une opération locale ou d'un nœud distant est appliquée à la table de base.

local_create_peer_timestamp

Valeur d'horodatage au niveau de la base de données locale lorsque la ligne a été insérée dans la base de données locale. 1

Une insertion provenant d'une opération locale ou d'un nœud distant est appliquée à la table de base.

sync_row_is_tombstone

La valeur 1 indique qu'une entrée de métadonnées correspond à une suppression dans la table de base.

Une ligne est supprimée de la table de base. La suppression peut provenir du nœud local ou distant.

last_change_datetime

Date et heure de la dernière mise à jour de la ligne de métadonnées.

Une ligne de cette table de suivi est insérée ou mise à jour.

restore_timestamp

Stocke la valeur de local_update_peer_timestamp au moment d'une restauration de base de données. Cette valeur est ensuite utilisée comme valeur d'horodatage de mise à jour locale.

Il s'agit en général de la valeur NULL, mais la valeur peut être définie par le processus de restauration. Prend la valeur NULL chaque fois qu'une ligne est mise à jour.

<Colonnes de filtrage> - ajoutez une colonne pour chaque colonne non-PK utilisée dans la clause WHERE de filtrage de toute étendue.

Obligatoire uniquement si une table est filtrée pour une ou plusieurs étendues. Stocke la valeur des colonnes sur lesquelles un filtre a été appliqué pour les insertions, les mises à jour et les suppressions.

Une ligne est insérée, mise à jour ou supprimée dans la table de base. La suppression peut provenir du nœud local ou distant.

1 Utilisée par Sync Framework lors de la synchronisation d'étendues qui se chevauchent. Considérez l'exemple suivant de mises à jour concernant une base de données qui synchronise l'étendue X avec le client A et l'étendue Y avec le client B. Les deux étendues contiennent la ligne Q.

  1. La ligne Q est mise à jour sur le client A, puis synchronisée avec la base de données.

  2. Le client B se synchronise avec la base de données et reçoit la mise à jour apportée à la ligne Q.

    Le client B ne connaît pas l'étendue X, de sorte que la modification du client A semble provenir de la base de données. Cette opération est réalisée à l'aide des valeurs de local_update_peer_key et local_update_peer_timestamp lors de la synchronisation avec le client B ou tout autre client qui ne synchronise pas l'étendue stockée dans update_scope_local_id pour la ligne Q.

  3. La ligne Q est mise à jour dans la base de données, puis synchronisée avec le client A.

    Le client A connaît l'étendue X, de sorte que les valeurs de scope_update_peer_key et scope_update_peer_timestamp sont utilisées lors de la synchronisation avec le client A ou tout autre client qui synchronise l'étendue X.

Nous vous recommandons de créer un schéma de base de données distinct pour la table de suivi et tous les autres objets relatifs aux métadonnées de synchronisation. Cela permet d'isoler les métadonnées des données qui figurent dans les tables de base. Pour des performances optimales, créez des index sur chaque table de suivi :

  • Si les données ne sont pas filtrées : utilisez la même clé primaire que la table de base et créez un index non cluster sur (local_update_peer_timestamp)

  • Si les données sont filtrées : utilisez la même clé primaire que la table de base et créez un index non cluster sur (local_update_peer_timestamp, <colonnes de filtrage>, <colonnes de clé primaire>)

Les exemples de code suivants créent dans le schéma Sync une table qui effectue le suivi des modifications pour la table Sales.Customer et ajoutent un index à la table.

CREATE TABLE Sync.Customer_Tracking(

    CustomerId uniqueidentifier NOT NULL PRIMARY KEY,          

    update_scope_local_id int NULL, 
    scope_update_peer_key int,
    scope_update_peer_timestamp bigint,
    local_update_peer_key int,
    local_update_peer_timestamp timestamp,

    create_scope_local_id int NULL,
    scope_create_peer_key int,
    scope_create_peer_timestamp bigint,
    local_create_peer_key int,
    local_create_peer_timestamp bigint,

    sync_row_is_tombstone int, 
    restore_timestamp bigint, 
    last_change_datetime datetime default NULL)

CREATE NONCLUSTERED INDEX NonClustered_Customer_Tracking
ON Sync.Customer_Tracking ([local_update_peer_timestamp])

Créer des déclencheurs pour remplir et mettre à jour les tables de suivi

Après avoir créé les tables de suivi, ajoutez un déclencheur INSERT, UPDATE et DELETE à chaque table de base. Lorsqu'un utilisateur ou Sync Framework insère, met à jour ou supprime une ligne dans une table de base, un déclencheur est activé et les métadonnées de cette ligne sont insérées ou mises à jour dans la table de suivi des modifications. Si Sync Framework a appliqué la modification à la table de base (parce qu'elle provenait d'un autre nœud), Sync Framework met à jour la table de suivi des modifications de façon à refléter l'origine de la modification.

L'exemple de code suivant crée un déclencheur qui met à jour les métadonnées de suivi des modifications dans la table Sales.Customer_Tracking lorsqu'une mise à jour est effectuée sur la table Sales.Customer. Pour obtenir des exemples de déclencheurs d'insertion et de suppression, consultez Scripts d'installation pour les rubriques de procédures sur le fournisseur de bases de données.

CREATE TRIGGER Customer_UpdateTrigger ON Sales.Customer FOR UPDATE
AS    
    UPDATE t    
    SET 
        update_scope_local_id = NULL, local_update_peer_key = 0, 
        restore_timestamp = NULL, last_change_datetime = GetDate() 
    FROM Sync.Customer_Tracking t JOIN inserted i ON t.[CustomerId] = i.[CustomerId]        

Gérer les données existantes dans la base de données

Les métadonnées de suivi des modifications de chaque table sont insérées et mises à jour par des déclencheurs définis sur la table de base. Par conséquent, les tables de suivi des modifications ne contiennent pas d'informations sur les lignes qui ont été insérées dans une table de base préalablement à l'ajout des déclencheurs. Pour gérer les données qui existent déjà dans la base de données, des métadonnées doivent leur être associées. Ensuite, lors de la première session de synchronisation, toutes les lignes seront envoyées à la base de données de destination en tant que nouvelles insertions. L'exemple de code suivant montre la commande à exécuter pour chaque table de base après que vous avez ajouté des déclencheurs à la table de base :

INSERT INTO [tracking table] ([pk columns], create_scope_local_id, local_create_peer_key, local_create_peer_timestamp, update_scope_local_id, local_update_peer_key, restore_timestamp, sync_row_is_tombstone)
SELECT [pk columns], NULL, 0, @@DBTS+1, NULL, 0, NULL, 0 from [base table] baseT left outer join [tracking table] trackingT
On baseT.[pk columns]=trackingT.[pk columns]
where tracking.[pk columns] is null

Créer des tables de suivi pour les métadonnées par étendue

Le suivi des métadonnées par étendue s'effectue généralement au moyen de deux tables dans chaque base de données :

  • La table d'informations d'étendue stocke la connaissance de synchronisation dans un format binaire pour chaque étendue. Une étendue est un regroupement logique de tables qui identifie les données qui doivent être synchronisées en tant qu'unité.

  • La table de mappage d'étendue identifie les tables d'une base de données qui appartiennent à une étendue particulière. Une table peut appartenir à plusieurs étendues. La table de mappage doit contenir une entrée pour chaque paire <étendue, table>.

Sync Framework utilise la connaissance pour déterminer quelles modifications envoyer à chaque base de données pendant la synchronisation. Les applications n'ont pas à utiliser la connaissance directement. Prenons l'exemple d'une topologie de synchronisation bidirectionnelle avec trois nœuds :

  1. Node1 et Node2 synchronisent toutes les modifications.

  2. Node1 se synchronise avec Node3.

  3. Un utilisateur effectue une mise à jour sur Node2.

  4. Node3 se synchronise avec Node2.

Lorsque Node3 se synchronise avec Node2, Node3 dispose déjà de la plupart des modifications provenant de Node2, car Node3 s'est d'abord synchronisé avec Node1. La connaissance permet à Sync Framework de reconnaître cela et de synchroniser uniquement la mise à jour qui s'est produite sur Node2. Pour plus d'informations sur la connaissance, consultez Présentation de la connaissance de synchronisation.

Les colonnes de la table d'informations d'étendue sont décrites dans le tableau suivant.

Colonne

Description

Mise à jour lorsque…

scope_id

Identificateur pour l'étendue, généralement un GUID.

Jamais mise à jour

scope_local_id

Identificateur entier pour l'étendue. Il doit s'agir d'une colonne IDENTITY.

Jamais mise à jour

scope_name

Nom de l'étendue.

Jamais mise à jour

scope_sync_knowledge

Représentation binaire de la connaissance de synchronisation pour chaque étendue.

Toutes les modifications ont été appliquées à une destination pour une session de synchronisation.

scope_tombstone_cleanup_knowledge

Représentation binaire de la connaissance oubliée pour chaque étendue. La connaissance oubliée est utilisée pour les métadonnées qui ont été nettoyées.

Toutes les modifications ont été appliquées à une destination pour une session de synchronisation.

scope_timestamp

Valeur d'horodatage lors de la dernière mise à jour de la ligne de métadonnées.

Une ligne de cette table de suivi est mise à jour.

scope_cleanup_timestamp

Valeur d'horodatage lors du dernier nettoyage des objets tombstone effectué pour cette étendue.

Les objets tombstone sont nettoyés pour une autre étendue où des tables se chevauchent.

L'exemple de code suivant crée une table d'informations d'étendue.

CREATE TABLE Sync.ScopeInfo(       
    scope_local_id int IDENTITY(1,1),
    scope_id uniqueidentifier default NEWID(),
    scope_name nvarchar(100) NOT NULL PRIMARY KEY,
    scope_sync_knowledge varbinary(max) NULL,
    scope_tombstone_cleanup_knowledge varbinary(max) NULL,
    scope_timestamp timestamp,
    scope_cleanup_timestamp bigint)

La table d'informations d'étendue est presque toujours interrogée afin de récupérer les informations sur une étendue particulière, d'après son nom. La clé primaire est donc définie sur la colonne scope_name.

Les colonnes de la table de mappage d'étendue sont décrites dans le tableau suivant.

Colonne

Description

Mise à jour lorsque…

table_name

Nom de la table.

Jamais mise à jour

scope_name

Nom de l'étendue.

Jamais mise à jour

Les exemples de code suivants créent une table de mappage d'étendue et un index sur cette table.

CREATE TABLE Sync.ScopeTableMap(      
    scope_name nvarchar(100) ,
    table_name nvarchar(100)     
    )

CREATE UNIQUE CLUSTERED INDEX Clustered_ScopeTableMap ON Sync.ScopeTableMap(scope_name, table_name)

Définir les étendues à synchroniser

Après avoir créé les tables d'étendue, choisissez la ou les étendues à synchroniser. Par exemple, vous pouvez définir une étendue nommée Sales et inclure les tables Customer, CustomerContact, OrderHeader et OrderDetail dans cette étendue. Lorsque l'étendue Sales est synchronisée, les modifications apportées aux quatre tables sont échangées entre les deux nœuds. La définition d'une étendue est un processus en deux parties :

  1. Ajouter des entrées à la table d'informations d'étendue et à la table de mappage d'étendue, comme dans l'exemple de code suivant.

    INSERT INTO Sync.ScopeInfo(scope_name) VALUES (''Sales'')
    INSERT INTO Sync.ScopeTableMap(scope_name, table_name) VALUES (''Sales'', ''Sales.Customer'')
    INSERT INTO Sync.ScopeTableMap(scope_name, table_name) VALUES (''Sales'', ''Sales.CustomerContact'')
    
  2. Spécifier le nom de l'étendue pour la propriété ScopeName de l'objet DbSyncProvider et ajouter un objet DbSyncAdapter pour chaque table que vous souhaitez inclure dans l'étendue. Pour plus d'informations, consultez « Code d'application pour ScopeName et Connection » dans Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server).

Important

Une fois qu'une étendue a été synchronisée, il est préférable de ne pas la modifier. La modification de tables dans l'étendue ou dans les clauses de filtrage de ces tables peut en effet aboutir à une non-convergence des données.

Étendues filtrées ou qui se chevauchent

Une étendue est filtrée si seul un sous-ensemble des lignes de la table de base est inclus dans l'étendue. Par exemple, vous pouvez définir une étendue filtrée nommée sales-WA qui contient uniquement les données des ventes réalisées dans l'État de Washington. Pour filtrer les données, la requête ou procédure que vous spécifiez pour la propriété SelectIncrementalChangesCommand de l'objet DbSyncAdapter doit inclure une clause WHERE qui sélectionne les données appropriées. La requête ou la procédure doit sélectionner des modifications basées sur des colonnes de filtrage dans la table de suivi plutôt que sur les colonnes de filtrage dans la table de base.

Les types de filtrage suivants ne sont pas pris en charge :

  • Filtrage de colonnes : toutes les colonnes doivent être incluses dans les requêtes ou procédures qui sélectionnent et appliquent les modifications.

  • Mises à jour des colonnes utilisées pour le filtrage : si un utilisateur met à jour une valeur dans une colonne utilisée pour le filtrage, une ligne passe d'une étendue à une autre. La ligne est envoyée à la nouvelle étendue à laquelle elle appartient désormais, mais n'est pas supprimée de l'ancienne étendue.

Deux étendues se chevauchent si elles partagent des données communes. Par exemple, la table products peut être incluse dans une étendue sales et une étendue inventory. Les étendues peuvent à la fois se chevaucher et être filtrées. Les scénarios suivants illustrent des situations qui peuvent conjuguer chevauchement et filtrage :

  • Scénario 1 :

    • L'étendue 1 est sales-WA. Cette étendue comprend products, orders avec un filtre state=WA et order_details avec un filtre state=WA.

    • L'étendue 2 est sales-OR. Cette étendue comprend products, orders avec un filtre state=OR et order_details avec un filtre state=OR.

    Dans ce scénario, l'intégralité de la table products est partagée par les deux étendues. Les tables orders et order_details appartiennent aux deux étendues, mais les filtres ne se chevauchent pas, de sorte que les étendues ne partagent pas de lignes de ces tables.

  • Scénario 2 :

    • L'étendue 1 est sales-WA. Cette étendue comprend products, orders avec un filtre state=WA et order_details avec un filtre state=WA.

    • L'étendue 2 est sales-Northwest. Cette étendue comprend products, orders avec un filtre state=WA OR state=ID et shippers.

    Dans ce scénario, à nouveau, l'intégralité de la table products est partagée par les deux étendues. La table orders appartient aux deux étendues et les filtres se chevauchent : les deux étendues partagent les lignes qui satisfont aux critères du filtre state=WA. Les tables shippers et order_details ne sont pas partagées entre les étendues.

Il existe de nombreux moyens de définir des étendues, mais le principe suivant doit être respecté : toutes les données qui sont synchronisées entre deux bases de données dans la topologie de synchronisation ne peuvent appartenir qu'à une seule étendue. Par exemple, dans le scénario 2 ci-dessus, les bases de données A et B pourraient synchroniser l'étendue 1, et les bases de données A et C l'étendue 2. Les bases de données A et B ne peuvent pas aussi synchroniser l'étendue 2, car les lignes products et orders appartiennent aux deux étendues.

Créer les procédures stockées permettant de sélectionner et mettre à jour les données et les métadonnées

Après avoir créé des tables de métadonnées, créez des requêtes SQL ou des procédures stockées (recommandé) pour sélectionner et appliquer des modifications aux tables de base et aux tables de métadonnées. Les procédures stockées sont recommandées pour des raisons de performances et de sécurité. Ces requêtes ou procédures sont spécifiées pour les commandes DbSyncAdapter suivantes. Ces commandes sont décrites sous « Adaptateur de synchronisation » dans Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server).

Les exemples de code suivants créent un ensemble de procédures stockées pour gérer les modifications de données et de métadonnées pour la table Sales.Customer. Pour des raisons de concision, les procédures pour sélectionner les données et gérer les mises à jour sont incluses, mais celles pour les insertions et les suppressions ne le sont pas. Pour obtenir des exemples de procédures d'insertion et de suppression, consultez Scripts d'installation pour les rubriques de procédures sur le fournisseur de bases de données. Pour obtenir un modèle qui vous permettra de créer plus facilement toutes ces procédures stockées, consultez Modèle de mise en service de serveur (non-SQL Server).

Dans l'exemple de code complet à la fin de cette rubrique, de nombreuses valeurs passées à ces procédures viennent de variables de session. Il s'agit de variables intégrées qui permettent à Sync Framework de passer des valeurs aux commandes lors d'une session de synchronisation. Pour plus d'informations sur les variables de session, consultez Procédure : utiliser des variables de session pour la synchronisation collaborative (non-SQL Server).

Procédure pour SelectIncrementalChangesCommand

create procedure Sync.sp_Customer_SelectChanges (
    @sync_min_timestamp bigint,
    @sync_metadata_only int,
    @sync_scope_local_id int,
    @sync_initialize int
)
as

--if @sync_initialize = 0
--begin
    -- Perform additional logic if required.
--end
    
begin
    select  t.CustomerId, 
            c.CustomerName,
            c.SalesPerson,
            c.CustomerType, 
            t.sync_row_is_tombstone,
            t.local_update_peer_timestamp as sync_row_timestamp, 
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then case when (t.restore_timestamp is null) then t.local_update_peer_timestamp else t.restore_timestamp end else t.scope_update_peer_timestamp end as sync_update_peer_timestamp,
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then t.local_update_peer_key else t.scope_update_peer_key end as sync_update_peer_key,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_timestamp else t.scope_create_peer_timestamp end as sync_create_peer_timestamp,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_key else t.scope_create_peer_key end as sync_create_peer_key
    from Sales.Customer c right join Sync.Customer_Tracking t on c.CustomerId = t.CustomerId
    where t.local_update_peer_timestamp > @sync_min_timestamp
end

Procédure pour UpdateCommand

CREATE PROCEDURE Sync.sp_Customer_ApplyUpdate (                                    
        @CustomerId uniqueidentifier,
        @CustomerName nvarchar(100),
        @SalesPerson nvarchar(100),
        @CustomerType nvarchar(100),
        @sync_min_timestamp bigint ,                                
        @sync_row_count int OUT,
        @sync_force_write int)        
AS      
    UPDATE c
    SET c.CustomerName = @CustomerName, c.SalesPerson = @SalesPerson, c.CustomerType = @CustomerType      
    FROM Sales.Customer c JOIN Sync.Customer_Tracking t ON c.CustomerId = t.CustomerId
    WHERE ((t.local_update_peer_timestamp <= @sync_min_timestamp) OR @sync_force_write = 1)
        AND t.CustomerId = @CustomerId  
    SET @sync_row_count = @@rowcount

Procédure pour UpdateMetadataCommand

create procedure Sync.sp_CustomerContact_UpdateMetadata (
        @CustomerId uniqueidentifier,
        @PhoneType nvarchar(100),
        @sync_scope_local_id int,
        @sync_row_is_tombstone int,
        @sync_create_peer_key int ,
        @sync_create_peer_timestamp bigint,                 
        @sync_update_peer_key int ,
        @sync_update_peer_timestamp timestamp,                      
        @sync_row_timestamp timestamp,
        @sync_check_concurrency int,        
        @sync_row_count int out)        
as  
    declare @was_tombstone int
    select @was_tombstone = sync_row_is_tombstone from Sync.CustomerContact_Tracking 
    where CustomerId = @CustomerId and PhoneType = @PhoneType
    
    if (@was_tombstone is not null and @was_tombstone=1 and @sync_row_is_tombstone=0)
        -- tombstone is getting resurrected, update creation version as well
        update Sync.CustomerContact_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [create_scope_local_id] = @sync_scope_local_id, 
            [scope_create_peer_key] = @sync_create_peer_key, 
            [scope_create_peer_timestamp] =  @sync_create_peer_timestamp, 
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId and PhoneType = @PhoneType   
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    else    
        update Sync.CustomerContact_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId and PhoneType = @PhoneType 
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    set @sync_row_count = @@rowcount

create procedure Sync.sp_Customer_UpdateMetadata (
        @CustomerId uniqueidentifier,
        @sync_scope_local_id int,
        @sync_row_is_tombstone int,
        @sync_create_peer_key int,
        @sync_create_peer_timestamp bigint,                 
        @sync_update_peer_key int,
        @sync_update_peer_timestamp timestamp,                      
        @sync_row_timestamp timestamp,
        @sync_check_concurrency int,        
        @sync_row_count int out)        
as  
    declare @was_tombstone int
    select @was_tombstone = sync_row_is_tombstone from Sync.Customer_Tracking 
    where CustomerId = @CustomerId
    
    if (@was_tombstone is not null and @was_tombstone=1 and @sync_row_is_tombstone=0)
        -- tombstone is getting resurrected, update creation version as well
        update Sync.Customer_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [create_scope_local_id] = @sync_scope_local_id, 
            [scope_create_peer_key] = @sync_create_peer_key, 
            [scope_create_peer_timestamp] =  @sync_create_peer_timestamp, 
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId          
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    else    
        update Sync.Customer_Tracking set
            [update_scope_local_id] = @sync_scope_local_id, 
            [scope_update_peer_key] = @sync_update_peer_key,
            [scope_update_peer_timestamp] = @sync_update_peer_timestamp,
            [local_update_peer_key] = 0,
            [restore_timestamp] = NULL,
            [sync_row_is_tombstone] = @sync_row_is_tombstone                        
        where CustomerId = @CustomerId          
        and (@sync_check_concurrency = 0 or local_update_peer_timestamp = @sync_row_timestamp)
    set @sync_row_count = @@rowcount

Procédure pour SelectRowCommand

create procedure Sync.sp_Customer_SelectRow
        @CustomerId uniqueidentifier,
        @sync_scope_local_id int
as
    select  t.CustomerId, 
            c.CustomerName,
            c.SalesPerson,
            c.CustomerType, 
            t.sync_row_is_tombstone,
            t.local_update_peer_timestamp as sync_row_timestamp, 
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then case when (t.restore_timestamp is null) then t.local_update_peer_timestamp else t.restore_timestamp end else t.scope_update_peer_timestamp end as sync_update_peer_timestamp,
            case when (t.update_scope_local_id is null or t.update_scope_local_id <> @sync_scope_local_id) 
                 then t.local_update_peer_key else t.scope_update_peer_key end as sync_update_peer_key,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_timestamp else t.scope_create_peer_timestamp end as sync_create_peer_timestamp,
            case when (t.create_scope_local_id is null or t.create_scope_local_id <> @sync_scope_local_id) 
                 then t.local_create_peer_key else t.scope_create_peer_key end as sync_create_peer_key
    from Sales.Customer c right join Sync.Customer_Tracking t on c.CustomerId = t.CustomerId    
    where c.CustomerId = @CustomerId 

Procédure pour SelectMetadataForCleanupCommand

CREATE PROCEDURE Sync.sp_Customer_SelectMetadata     
    @metadata_aging_in_days int,
    @sync_scope_local_id int
AS
    IF @metadata_aging_in_days = -1
        BEGIN
            SELECT  CustomerId,
                    local_update_peer_timestamp as sync_row_timestamp,  
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then case when (restore_timestamp is null) then local_update_peer_timestamp else restore_timestamp end else scope_update_peer_timestamp end as sync_update_peer_timestamp,
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then local_update_peer_key else scope_update_peer_key end as sync_update_peer_key,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_timestamp else scope_create_peer_timestamp end as sync_create_peer_timestamp,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_key else scope_create_peer_key end as sync_create_peer_key
            FROM Sync.Customer_Tracking
            WHERE sync_row_is_tombstone = 1
        END
    
    ELSE
        BEGIN
            SELECT  CustomerId,
                    local_update_peer_timestamp as sync_row_timestamp,  
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then case when (restore_timestamp is null) then local_update_peer_timestamp else restore_timestamp end else scope_update_peer_timestamp end as sync_update_peer_timestamp,
                    case when (update_scope_local_id is null or update_scope_local_id <> @sync_scope_local_id) 
                        then local_update_peer_key else scope_update_peer_key end as sync_update_peer_key,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_timestamp else scope_create_peer_timestamp end as sync_create_peer_timestamp,
                    case when (create_scope_local_id is null or create_scope_local_id <> @sync_scope_local_id) 
                        then local_create_peer_key else scope_create_peer_key end as sync_create_peer_key
            FROM Sync.Customer_Tracking
            WHERE sync_row_is_tombstone = 1 AND
            DATEDIFF(day, last_change_datetime, GETDATE()) > @metadata_aging_in_days
        END

Conclusion

Cette rubrique vous a expliqué pas à pas comment approvisionner une base de données pour le suivi des modifications. Une fois approvisionnée, une base de données peut être synchronisée avec d'autres nœuds. Pour plus d'informations sur la façon de configurer et d'exécuter la synchronisation, consultez la rubrique suivante : Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server).

Voir aussi

Autres ressources

Synchronisation d'autre bases de données compatibles ADO.NET

Procédure : configurer et exécuter la synchronisation collaborative (non-SQL Server)