共用方式為


HOW TO:佈建伺服器資料庫來進行共同作業同步處理 (非 SQL Server)

注意

文件中同步處理其他 ADO.NET 相容的資料庫這一節的主題是用來示範如何使用 Sync Framework 來同步處理 SQL Server 以外的資料庫。在這一版中,程式碼範例中使用的是SQL Server,但是程式碼可用於其他 ADO.NET 相容的資料庫,只需要針對 SQL Server 特有的物件 (例如 SqlConnection) 以及顯示的 SQL 查詢進行某些修改。如需 SQL Server 同步處理的詳細資訊,請參閱HOW TO:設定及執行共同作業同步處理 (SQL Server)

本主題描述如何佈建 DbSyncProvider 所同步處理的資料庫,以便可以在該資料庫內追蹤累加式資料變更。變更會加以追蹤,好讓同步處理工作階段期間可以將變更套用到其他節點。若要為 Sync Framework 佈建資料庫,請遵循以下步驟執行:

  1. 為資料庫啟用快照集隔離

  2. 識別要同步處理的資料表

  3. 建立追蹤資料表來儲存每個資料表的中繼資料,並在這些資料表上建立索引

  4. 在每個基底資料表上建立觸發程序,以擴展及更新追蹤資料表

  5. (選擇性) 處理資料庫中的現有資料

  6. 建立追蹤資料表來儲存每個範圍的中繼資料,並在這個資料表上建立索引

  7. 定義要同步處理的範圍,該範圍會指定哪些資料表會視為一個單位來同步處理

  8. 建立預存程序來選取及更新資料和中繼資料

SqlCeSyncProvider 同步處理的資料庫並不需要這些步驟,初始化資料庫時是由 Sync Framework 來處理佈建作業。

在佈建資料庫之後,可以將它與其他節點同步處理。如需如何設定及執行同步處理的詳細資訊,請參閱 HOW TO:設定及執行共同作業同步處理 (非 SQL Server)

為資料庫啟用快照集隔離

在同步處理工作階段的變更列舉階段期間,Sync Framework 會在快照集隔離之下啟動交易。若要在快照集隔離之下啟動交易,您必須將 ALLOW_SNAPSHOT_ISOLATION 資料庫選項設定為 ON,如下列程式碼範例所示:

ALTER DATABASE [database name] SET ALLOW_SNAPSHOT_ISOLATION ON

如需詳細資訊,請參閱《SQL Server 線上叢書》。

識別要同步處理的資料表

佈建資料庫的第一個步驟是識別將會同步處理的資料表。每個資料表都必須有一個主索引鍵。假設有以下的程式碼範例。它會示範 SyncSamplesDb_Peer1 資料庫中的 Sales.Customer 資料表結構描述。

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)

您所同步處理的每一個資料表都具有關聯的 DbSyncAdapter 物件,而且您會在該物件的 RowIdColumns 集合中指定主索引鍵。如需詳細資訊,請參閱 HOW TO:設定及執行共同作業同步處理 (非 SQL Server)

資料表可以是空的或者包含現有的資料。如果資料表包含應該同步處理的現有資料列,您必須確定每一個資料列在適當的變更追蹤資料表內都有中繼資料項目。如需詳細資訊,請參閱處理資料庫中的現有資料。

針對每個資料表的中繼資料建立追蹤資料表

Sync Framework 需要一個方式來追蹤,哪些資料列從上一次兩個節點之間的同步處理工作階段之後已經變更。變更會以兩種不同類型的中繼資料來表示:

  • 每個資料表的中繼資料,它會追蹤每個同步處理之資料表的插入、更新和刪除。

  • 每個範圍的中繼資料,它會追蹤每一個節點已經從其他節點收到的變更。

每個資料表的中繼資料是使用每個基底資料表的一個追蹤資料表加以追蹤。基底資料表和追蹤資料表必須存在於 DbSyncProvider 所同步處理的每一個資料庫中。追蹤資料表的主索引鍵與基底資料表中的相同,並需要其他資料行。下表描述這些資料行。其他資料行的名稱不必與列出的資料行相同,但是在順序和類型方面必須與存取追蹤資料表的查詢或程序相符。某些程序已包含在建立預存程序來選取及更新資料和中繼資料中。

資料行 描述 更新時機…

<基底資料表的主索引鍵 (PK)> - 包含每一個 PK 資料行的資料行。

基底資料表的主索引鍵資料行。

資料列會插入基底資料表。插入可以來自本機或遠端的節點。

update_scope_local_id

執行上一次更新或刪除之範圍的識別碼。如果是來自本機節點的更新或刪除,此資料行會是 NULL。

參考範圍資訊資料表中的 scope_local_id 資料行。如需詳細資訊,請參閱<針對每個範圍的中繼資料建立追蹤資料表>。

來自遠端節點的更新或刪除會套用至基底資料表。

scope_update_peer_key

執行上一次更新或刪除之節點的識別碼。

來自遠端節點的更新或刪除會套用至基底資料表。

scope_update_peer_timestamp

當初更新或刪除資料列時,在遠端資料庫中的時間戳記值。

來自遠端節點的更新或刪除會套用至基底資料表。

local_update_peer_key

本機節點的識別碼。這個資料行將會針對每一個資料列包含 0 的值,除非從備份還原本機資料庫。1

來自本機作業或遠端節點的更新或刪除會套用至基底資料表。

local_update_peer_timestamp

當初更新或刪除本機資料庫中的資料列時,在本機資料庫中的時間戳記值。1

來自本機作業或遠端節點的更新或刪除會套用至基底資料表。

create_scope_local_id

執行插入之範圍的識別碼。如果是來自本機節點的更新或刪除,此資料行會是 NULL。

參考範圍資訊資料表中的 scope_local_id 資料行。如需詳細資訊,請參閱 HOW TO:佈建伺服器資料庫來進行共同作業同步處理 (非 SQL Server)中的<針對每個範圍的中繼資料建立追蹤資料表>。

來自遠端節點的插入會套用至基底資料表。

scope_create_peer_key

執行插入之節點的識別碼。

來自遠端節點的插入會套用至基底資料表。

scope_create_peer_timestamp

當初插入資料列時,在遠端資料庫中的時間戳記值。

來自遠端節點的插入會套用至基底資料表。

local_create_peer_key

本機節點的識別碼。這個資料行將會針對每一個資料列包含 0 的值,除非從備份還原本機資料庫。1

來自本機作業或遠端節點的插入會套用至基底資料表。

local_create_peer_timestamp

當初資料列插入至本機資料庫時,在本機資料庫中的時間戳記值。1

來自本機作業或遠端節點的插入會套用至基底資料表。

sync_row_is_tombstone

值 1 表示中繼資料項目是供基底資料表中的刪除使用。

資料列會從基底資料表刪除。刪除可以來自本機或遠端的節點。

last_change_datetime

上一次更新中繼資料列的日期和時間。

將會插入或更新這個追蹤資料表中的資料列。

restore_timestamp

在還原資料庫時,儲存 local_update_peer_timestamp 的值。然後此值會當做本機更新時間戳記值使用。

它通常會是 NULL,但是可由還原處理序設定。每當更新資料列時都設定為 NULL。

<篩選資料行> - 針對任何範圍之篩選 WHERE 子句中所使用的每一個非 PK 資料行新增資料行。

只有針對一個或多個範圍篩選資料表時,才需要此項目。儲存篩選之資料行的插入、更新和刪除的值。

從基底資料表插入、更新或刪除資料列。刪除可以來自本機或遠端的節點。

1 在同步處理重疊的範圍時,由 Sync Framework 所使用。假設下列是更新資料庫的範例,該資料庫會將範圍 X 與用戶端 A 同步處理,並將範圍 Y 與用戶端 B 同步處理。兩個範圍都包含資料列 Q。

  1. 資料列 Q 會在用戶端 A 更新,然後與資料庫同步處理。

  2. 用戶端 B 會與資料庫同步處理,並接收資料列 Q 的更新。

    用戶端 B 沒有察覺到範圍 X,所以當出現來自用戶端 A 的變更時,必須就像來自資料庫一樣。當與用戶端 B 或是未與資料列 Q 之 update_scope_local_id 內儲存的範圍同步處理的任何其他用戶端同步處理時,便會藉由使用 local_update_peer_key 和 local_update_peer_timestamp 中的值來達成這個結果。

  3. 資料列 Q 會在資料庫更新,然後與用戶端 A 同步處理。

    用戶端 A 有察覺到範圍 X,所以當與用戶端 A 或與範圍 X 同步處理之任何其他用戶端同步處理時,就會使用 scope_update_peer_key 和 scope_update_peer_timestamp 中的值。

我們建議您針對與同步處理中繼資料有關的追蹤資料表和所有其他物件建立個別的資料庫結構描述。這有助於隔離中繼資料及基底資料表中的資料。如需取得最佳效能,請在每個追蹤資料表上建立索引:

  • 如果未篩選資料,請使用與基底資料表相同的主索引鍵,並在 (local_update_peer_timestamp) 上建立非叢集索引。

  • 如果已篩選資料,請使用與基底資料表相同的主索引鍵,並在 ((local_update_peer_timestamp, <篩選資料行>, <主索引鍵資料行>) 上建立非叢集索引

下列程式碼範例會在 Sync 結構描述中建立資料表,該資料表會追蹤 Sales.Customer 資料表的變更,並將索引加入至此資料表。

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])

建立觸發程序來擴展及更新追蹤資料表

建立追蹤資料表之後,將 INSERT、UPDATE 和 DELETE 觸發程序加入至每個基底資料表。當使用者或 Sync Framework 插入、更新或刪除基底資料表中的資料列時,就會引發觸發程序,而且變更追蹤資料表內會插入或更新該資料列的中繼資料。如果 Sync Framework 將變更套用到基底資料表 (因為它來自另一個節點),Sync Framework 就會更新變更追蹤資料表來反映變更的來源。

下列程式碼範例會建立觸發程序,在更新 Sales.Customer 資料表時,更新 Sales.Customer_Tracking 資料表中的變更追蹤中繼資料。如需插入和刪除觸發程序的範例,請參閱資料庫提供者的安裝指令碼 HOW-TO 主題

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]        

處理資料庫中的現有資料

基底資料表上的觸發程序會插入及更新每個資料表的變更追蹤中繼資料。因此,變更追蹤資料表不會包含在加入觸發程序之前便已插入基底資料表內之任何資料列的相關資訊。若要處理資料庫中的現有資料,應該針對現有的資料插入中繼資料。然後,在第一個同步處理工作階段期間,所有資料列都會當做新的插入傳送到目的地資料庫。下列程式碼範例會顯示在您於基底資料表中加入觸發程序之後,要針對每一個基底資料表執行的命令:

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

針對每個範圍的中繼資料建立追蹤資料表

每個範圍的中繼資料通常會使用每個資料庫中的兩個資料表來追蹤:

  • 範圍資訊資料表會以二進位格式,儲存每個範圍的同步處理知識。範圍是資料表的邏輯群組,可定義哪些資料應該視為一個單位進行同步處理。

  • 範圍對應表會識別資料庫中的哪些資料表屬於特定的範圍。一個資料表有可能屬於一個以上的範圍。對應表在每一組 <範圍, 資料表> 中只能包含一個項目。

Sync Framework 會使用知識,以判斷在同步處理期間要將哪些變更傳送到每一個資料庫。應用程式不必直接使用知識。假設有一個雙向同步處理拓撲,其中包含三個節點:

  1. Node1 和 Node2 會同步處理所有變更。

  2. Node1 會與 Node3 同步處理。

  3. 使用者會在 Node2 上執行更新。

  4. Node3 會與 Node2 同步處理。

當 Node3 與 Node2 同步處理時,Node3 已經具有來自 Node2 的大部分變更,因為 Node3 已經與 Node1 先同步處理。知識可以讓 Sync Framework 識別這種情形,並同步處理只在 Node2 上發生的更新。如需知識的詳細資訊,請參閱了解同步處理知識

下表描述範圍資訊資料表的資料行。

資料行 描述 更新時機…

scope_id

範圍的識別碼,通常是 GUID。

永遠不會更新

scope_local_id

範圍的整數識別碼。這應該是 IDENTITY 資料行。

永遠不會更新

scope_name

範圍的名稱。

永遠不會更新

scope_sync_knowledge

每個範圍之同步處理知識的二進位表示。

所有的變更都已套用到同步處理工作階段的目的地。

scope_tombstone_cleanup_knowledge

每個範圍之「遺忘知識」(Forgotten Knowledge) 的二進位表示。遺忘知識是用於已清除的中繼資料。

所有的變更都已套用到同步處理工作階段的目的地。

scope_timestamp

上一次更新中繼資料列的時間戳記值。

這個追蹤資料表中的資料列經過更新時。

scope_cleanup_timestamp

當針對這個範圍執行最新標記清除時的時間戳記值。

針對有重疊資料表的另一個範圍清除標記時。

下列程式碼範例會建立範圍資訊資料表。

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)

要擷取有關特定範圍的資訊 (根據範圍名稱) 時,幾乎一定會查詢範圍資訊資料表。因此,主索引鍵會定義在 scope_name 資料行上。

下表描述範圍對應表的資料行。

資料行 描述 更新時機…

table_name

資料表的名稱。

永遠不會更新

scope_name

範圍的名稱。

永遠不會更新

下列程式碼範例會在該資料表上建立範圍對應表和索引。

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)

定義要同步處理的範圍

在您建立範圍資料表之後,請決定要同步處理的一個或多個範圍。例如,您可以定義名為 Sales 的範圍,並在該範圍中包含 CustomerCustomerContactOrderHeaderOrderDetail 資料表。當同步處理 Sales 範圍時,會在兩個節點之間交換對四個資料表所做的變更。定義範圍的程序包含兩個部分:

  1. 將項目加入至範圍資訊資料表及範圍對應表,如下列程式碼範例所示。

    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. 針對 DbSyncProvider 物件的 ScopeName 屬性指定範圍名稱,並針對您想要包含在範圍中的每一個資料表加入 DbSyncAdapter 物件。如需詳細資訊,請參閱 HOW TO:設定及執行共同作業同步處理 (非 SQL Server)中的<ScopeName 和連接的應用程式程式碼>。

注意

當範圍初次同步處理後,就不應該變更此範圍。變更範圍中的資料表或篩選這些資料表的子句可能會導致非聚合的資料。

已篩選及重疊的範圍

如果只有基底資料表的資料列子集包含在範圍內時,該範圍就是經過篩選的。例如,您可以定義一個名為 sales-WA 的已篩選範圍,其中只包含美國華盛頓州的銷售資料。若要篩選資料,您針對 DbSyncAdapter 物件的 SelectIncrementalChangesCommand 屬性所指定的查詢或程序必須包含一個可選取適當資料的 WHERE 子句。查詢或程序應該根據追蹤資料表中的篩選資料行而非基底資料表中的篩選資料行選取變更。

下列篩選類型不受支援:

  • 資料行篩選:所有資料行都必須包含在可選取及套用變更的查詢或程序中。

  • 用於篩選之資料行的更新:如果使用者在用於篩選的資料行中更新值,資料列就會從某個範圍移到另一個範圍。此資料列會傳送到其現在所屬的新範圍,但是不會從舊的範圍中刪除此資料列。

如果兩個範圍之間共用共同的資料,這兩個範圍就會重疊。例如,products 資料表可能會包含在 sales 範圍和 inventory 範圍中。範圍可以同時是重疊且經過篩選的。下列案例示範可能發生的篩選及重疊的方式:

  • 案例 1:

    • 範圍 1 是 sales-WA。此範圍包括:productsorders (含有 state=WA 的篩選) 及 order_details (含有 state=WA 的篩選)。

    • 範圍 2 是 sales-OR。此範圍包括:productsorders (含有 state=OR 的篩選) 及 order_details (含有 state=OR 的篩選)。

    在此案例中,兩個範圍會共用整個 products 資料表。ordersorder_details 資料表位於兩個範圍中,但是篩選並未重疊,因此範圍不會共用這些資料表中的資料列。

  • 案例 2:

    • 範圍 1 是 sales-WA。此範圍包括:productsorders (含有 state=WA 的篩選) 及 order_details (含有 state=WA 的篩選)。

    • 範圍 2 是 sales-Northwest。此範圍包括:productsorders (含有 state=WA OR state=ID 的篩選) 及 shippers

    在此案例中,兩個範圍會再次共用整個 products 資料表。orders 資料表位於兩個範圍中而且篩選會重疊:兩個範圍會共用可滿足 state=WA 篩選的資料列。shippersorder_details 資料表不會在範圍之間共用。

有許多不同的方法可以定義範圍,但是必須遵循以下基本方針:在同步處理拓撲內的一對資料庫之間同步處理的任何資料都只能屬於一個範圍。例如,上述的案例 2、資料庫 A 和資料庫 B 可以同步處理範圍 1,而資料庫 A 和資料庫 C 可以同步處理範圍 2。資料庫 A 和資料庫 B 無法同步處理範圍 2,因為 productsorders 資料列屬於這兩個範圍。

建立預存程序來選取及更新資料和中繼資料

在建立中繼資料表之後,建立 SQL 查詢或預存程序 (建議使用),以選取變更以及將變更套用至基底資料表和中繼資料表。基於效能和安全性的理由,建議使用預存程序。這些查詢或程序是針對下列 DbSyncAdapter 命令所指定。HOW TO:設定及執行共同作業同步處理 (非 SQL Server)中的<同步處理配接器>會描述這些命令。

下列程式碼範例會建立一組預存程序,為 Sales.Customer 資料表處理資料和中繼資料變更。為求簡潔,範例中包含了選取資料和處理更新的預存程序,但不包含插入和刪除的預存程序。如需插入和刪除程序的範例,請參閱資料庫提供者的安裝指令碼 HOW-TO 主題。如需可讓您更輕鬆地建立所有這些預存程序的範本,請參閱伺服器佈建範本

在本主題結尾的完整程式碼範例中,傳遞給這些程序的許多值都是來自「工作階段變數」(Session Variable)。這些都是內建變數,可在同步處理工作階段期間,啟用 Sync Framework 傳遞值給命令。如需工作階段變數的詳細資訊,請參閱 HOW TO:使用共同作業同步處理的工作階段變數

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

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

UpdateMetadataCommand 的程序

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

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 

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

結論

本主題已逐步引導您佈建資料庫來進行變更追蹤。在佈建資料庫之後,可以將它與其他節點同步處理。如需如何設定及執行同步處理的詳細資訊,請參閱以下主題:HOW TO:設定及執行共同作業同步處理 (非 SQL Server)

請參閱

概念

同步處理其他 ADO.NET 相容的資料庫
HOW TO:設定及執行共同作業同步處理 (非 SQL Server)