Share via


套用變更

目的地提供者取得變更批次並處理衝突之後,變更就會套用至目的地複寫。這項作業一般是在目的地提供者的 ProcessChangeBatch (適用於 Managed 程式碼) or ProcessChangeBatch (適用於 Unmanaged 程式碼) 方法中完成,而使用 Sync Framework 所提供的變更套用者物件最容易達成。

套用變更的方式

目的地提供者取得來源提供者的變更批次之後,目的地提供者就會將變更套用至目的地複寫。Sync Framework 所提供的變更套用者物件可以透過建立 NotifyingChangeApplier 物件 (適用於 Managed 程式碼),或呼叫 IProviderSyncServices::CreateChangeApplier (適用於 Unmanaged 程式碼) 來取得。ApplyChanges (適用於 Managed 程式碼) 或 ApplyChanges (適用於 Unmanaged 程式碼) 方法會偵測衝突,並在目的地提供者上呼叫方法,將變更套用至目的地複寫。

處理變更項目

為了處理一般變更項目,變更套用者會先在來源提供者上呼叫 LoadChangeData (適用於 Managed 程式碼) 或 ISynchronousDataRetriever::LoadChangeData (適用於 Unmanaged 程式碼) 方法,以啟動資料傳輸。此方法會傳回代表資料傳輸機制的 object (適用於 Managed 程式碼) 或 IUnknown 介面 (適用於 Unmanaged 程式碼)。然後變更套用者在目的地提供者上呼叫 SaveItemChange (適用於 Managed 程式碼) 或 ISynchronousNotifyingChangeApplierTarget::SaveChange (適用於 Unmanaged 程式碼) 方法,再傳遞資料傳輸物件做為儲存變更內容的一部分。接著,目的地提供者就可以傳輸資料給目的地複寫。任何取得資料或處理變更作業失敗都會使用 RecordRecoverableErrorForItem (適用於 Managed 程式碼) 或 ISaveChangeContext::SetRecoverableErrorOnChange (適用於 Unmanaged 程式碼) 方法來表示。此方法會將此項目的可復原錯誤記錄在包含於變更批次內學習到的知識物件中。

更新學習到的知識

進行變更套用時,變更套用者會更新包含於變更批次中之學習到的知識。學習到的知識是投射到變更批次中變更上的來源複寫知識,代表目的地複寫在套用變更批次中所有變更時,會知道的事項。學習到的知識是以下列方式更新:

  • 如果由於中斷或取消而只套用了變更子集,變更套用者會使用 Project 運算子,將知識只限定於已套用的變更集。

  • 如果套用一些變更時失敗,變更套用者也會從知識中加以排除。

請注意,提供者實作器不必手動執行這些 Project、Union 和 Exclude 運算,這是因為變更套用者會代表提供者執行這些運算。

儲存已更新之目的地知識

學習到的知識更新之後,會與目的地複寫的知識合併,目的地提供者必須自動以這項知識取代目的地複寫的知識。如果批次中所有變更都在單一交易之中套用時,這種不可部分完成性是透過每個批次只儲存一次已更新知識來達成。變更套用者會在每個批次結束時,目的地提供者上呼叫 StoreKnowledgeForScope (適用於 Managed 程式碼) 或 ISynchronousNotifyingChangeApplierTarget::SaveKnowledge (適用於 Unmanaged 程式碼) 方法來協助這項作業。傳遞給此方法的知識是要套用於目的地複寫的已更新知識。或者,目的地提供者也會呼叫 GetUpdatedDestinationKnowledge (適用於 Managed 程式碼) 或 ISaveChangeContext::GetKnowledgeForScope (適用於 Unmanaged 程式碼) 方法,以取得更新的知識。

當提供者使用變更單位以取代子項目時,套用變更的方式會有一些差異。如需詳細資訊,請參閱同步處理變更單位

階層複寫的特殊考量

階層複寫的同步處理可能會遇到因從來源批次處理變更集至目的地而產生的一些複雜性,Sync Framework 不支援資料階層的概念,因此,完全要靠提供者來正確處理這些情況。

最常見的複雜性是更新作業中父子關係的順序。例如,請考慮下列案例:

  1. 來源複寫已經建立了新資料夾,並在其中建立一組新項目。

  2. 目的地提供者會要求來源提供者的變更。處理來源提供者傳送的變更批次。但是包含父資料夾建立的變更批次會在包含子項目的變更批次之後才送達。

  3. 目的地提供者必須決定存放在第一批次中送達的項目集,因為有關其存放位置的資訊要在第二批次才會送達。

減少階層式更新

如果有更新,減低父/子關係複雜性最簡單的方式是讓來源提供者負責為全域識別碼排序。這樣父項目一定會在其子項目之前送達。

當目的地提供者處理在階層式存放區中更新的傳輸時,可能會接到過時的父/子關係。目的地提供者必須能夠還原此情況,或者是卸除過時變更而在其知識中記下例外狀況,或者是將變更排入佇列,以便稍後套用。由於項目大小可能會很大,直接卸除變更並記下知識例外狀況可能是最實際有效的做法。

減少階層式刪除

目的地提供者會判斷項目是否為容器項目。對於空白容器,可能會立即加以刪除。但是如果容器中有尚未標記為刪除的項目,提供者有下列選擇:

  • 將刪除排入佇列,以便稍後處理。容器的所有子項目都刪除之後,就可以觸發實際的刪除。

  • 卸除此要求並在知識中設定例外狀況,指出未按順序接到項目。

為了解決父項已經在階層中刪除,然後再加入子項的案例,要遵守以下規則:將刪除排入佇列的有效性只到成對工作階段結束為止,而並不會持續到參與者之間。

請參閱

參考

IProviderSyncServices 介面
ISynchronousNotifyingChangeApplier::ApplyChanges
IAsynchronousNotifyingChangeApplier::ApplyChanges
ISynchronousNotifyingChangeApplierTarget::SaveKnowledge
IAsynchronousNotifyingChangeApplierTarget::SaveKnowledge
ISynchronousDataRetriever 介面
IAsynchronousDataRetriever 介面
ISyncKnowledge::ExcludeItem
ISyncKnowledge::Union
ISaveChangeContext 介面
NotifyingChangeApplier
ApplyChanges
StoreKnowledgeForScope
IChangeDataRetriever
ExcludeItem
Contains
SaveChangeContext

概念

同步處理提供者
了解同步處理知識