共用方式為


IKnowledgeSyncProvider::ProcessChangeBatch

透過偵測衝突及將變更套用到項目存放區來處理一組變更。

HRESULT ProcessChangeBatch(
  CONFLICT_RESOLUTION_POLICY resolutionPolicy,
  ISyncChangeBatch * pSourceChangeBatch,
  IUnknown * pUnkDataRetriever,
  ISyncCallback * pCallback,
  SYNC_SESSION_STATISTICS * pSyncSessionStatistics);

參數

  • resolutionPolicy
    [in] 當這個方法套用變更時要使用的衝突解決原則。
  • pSourceChangeBatch
    [in] 要在本機套用之來源提供者的變更批次。
  • pUnkDataRetriever
    [in] 可用來擷取變更資料的物件。它可以是 ISynchronousDataRetriever 物件或提供者特有的物件。
  • pCallback
    [in] 在變更套用期間接收事件通知的物件。
  • pSyncSessionStatistics
    [in, out] 追蹤變更統計資料。若為使用自訂變更套用的提供者,就必須使用變更套用的結果來更新這個物件。

傳回值

  • S_OK

  • 提供者決定的錯誤碼

備註

當來源變更包含變更單位變更時,目的地提供者必須判斷哪些變更單位版本 (如果有的話) 要包含在傳送至變更套用者的目的地版本批次中。這項決定會取決於來源提供者的變更類型,以及項目是否在目的地複寫上標示為已刪除。如需詳細資訊,請參閱同步處理變更單位

範例

以下範例會示範如何實作 ProcessChangeBatch。第一個範例會示範如何建立 ISynchronousNotifyingChangeApplier 物件,然後呼叫 ISynchronousNotifyingChangeApplier::ApplyChanges 以套用變更至目的地複寫。第二個範例會實作第一個範例中所使用的 m_pMetadataMgr->GetItemBatchVersions 方法。此方法會列舉包含於來源變更批次中的變更,然後使用 IDestinationChangeVersionsBuilder 物件,建立相對應的目的地版本清單。

STDMETHODIMP CXMLProvider::ProcessChangeBatch(
    CONFLICT_RESOLUTION_POLICY resolutionPolicy,
    ISyncChangeBatch * pSourceChangeBatch,
    IUnknown * pUnkDataRetriever,
    ISyncCallback * pCallback,
    SYNC_SESSION_STATISTICS * pSyncSessionStatistics)
{
    HRESULT hr = E_UNEXPECTED;

    if (NULL == pSourceChangeBatch || NULL == pUnkDataRetriever || NULL == pSyncSessionStatistics)
    {
        hr = E_POINTER;
    }
    else
    {
        IEnumSyncChanges* pDestinationChangeEnum = NULL;

        _ASSERT(NULL != m_pMetadataMgr);

        // Obtain the local (destination) versions for the items in the source change batch.
        hr = m_pMetadataMgr->GetItemBatchVersions(pSourceChangeBatch, &pDestinationChangeEnum);
        if (SUCCEEDED(hr))
        {
            IProviderSyncServices* pProviderSvc = NULL;
            hr = GetProviderSyncServices(&c_idParams, &pProviderSvc);
            if (SUCCEEDED(hr))
            {
                // Create a standard change applier from Sync Framework.
                ISynchronousNotifyingChangeApplier* pChangeApplier = NULL;
                hr = pProviderSvc->CreateChangeApplier(IID_ISynchronousNotifyingChangeApplier,
                    (void**)&pChangeApplier);
                if (SUCCEEDED(hr))
                {
                    ISyncKnowledge* pDestinationKnowledge = NULL;
                    hr = m_pMetadataMgr->GetKnowledge(&pDestinationKnowledge);
                    if (SUCCEEDED(hr))
                    {
                        // Have the change applier process the change batch and apply changes.
                        // This method will call the change applier target methods to save
                        // changes and conflicts.  It will also pass the data retriever
                        // interface to the change applier target so it can retrieve item data.
                        hr = pChangeApplier->ApplyChanges(resolutionPolicy, pSourceChangeBatch, 
                            pUnkDataRetriever, pDestinationChangeEnum, pDestinationKnowledge, 
                            NULL, this, m_pSessionState, pCallback);
                        
                        pDestinationKnowledge->Release();
                    }

                    pChangeApplier->Release();
                }

                pProviderSvc->Release();
            }

            pDestinationChangeEnum->Release();
        }
    }

    return hr;
}
STDMETHODIMP CMetadataMgr::GetItemBatchVersions(
    ISyncChangeBatch * pRemoteSyncChangeBatch,
    IEnumSyncChanges ** ppLocalVersionsEnum)
{
    HRESULT hr = E_UNEXPECTED;

    if (NULL == pRemoteSyncChangeBatch || NULL == ppLocalVersionsEnum)
    {
        hr = E_POINTER;
    }
    else
    {
        IProviderSyncServices* pProvSvc;
        hr = GetProviderSyncServices(&c_idParams, &pProvSvc);
        if (SUCCEEDED(hr))
        {
            IDestinationChangeVersionsBuilder* pDestChangeBuilder = NULL;
            hr = pProvSvc->CreateDestinationChangeVersionsBuilder(&pDestChangeBuilder);
            if (SUCCEEDED(hr))
            {
                IEnumSyncChanges* pRemoteEnum = NULL;
                hr = pRemoteSyncChangeBatch->GetChangeEnumerator(&pRemoteEnum);
                if (SUCCEEDED(hr))
                {
                    ULONG cFetched;

                    ISyncChange* pChange;
                    SYNC_GID gidItem;
                    DWORD cbID = sizeof(gidItem);
                    DWORD dwFlags;
                    SYNC_VERSION verCurrent;
                    SYNC_VERSION verCreation;
                    HRESULT hrEnum = S_OK;
                    while (S_OK == hrEnum && SUCCEEDED(hr))
                    {
                        pChange = NULL;
                        hrEnum = pRemoteEnum->Next(1, &pChange, &cFetched);
                        if (S_OK == hrEnum)
                        {
                            hr = pChange->GetRootItemId((BYTE*)&gidItem, &cbID);
                            if (SUCCEEDED(hr))
                            {
                                // Try to find the item in the local (destination) metadata.
                                IItemMetadata* pItem = NULL;
                                hr = FindItemMetadataByGlobalId((BYTE*)&gidItem, &pItem);
                                if (S_OK == hr)
                                {
                                    // S_OK means the item exists in our local store.
                                    // Extract its version and tombstone information.
                                    dwFlags = 0;

                                    BOOL fTombstone = FALSE;
                                    hr = pItem->GetIsDeleted(&fTombstone);
                                    if (SUCCEEDED(hr))
                                    {
                                        if (fTombstone)
                                        {
                                            dwFlags = SYNC_CHANGE_FLAG_DELETED;
                                        }
                                    }

                                    if (SUCCEEDED(hr))
                                    {
                                        hr = pItem->GetChangeVersion(&verCurrent);
                                        if (SUCCEEDED(hr))
                                        {
                                            hr = pItem->GetCreationVersion(&verCreation);                                            
                                        }
                                    }

                                    pItem->Release();
                                }
                                else if (S_FALSE == hr)
                                {
                                    // S_FALSE means this item does not exist in our local store.
                                    // Set versions to 0 and flag it as a new item.
                                    verCurrent.dwLastUpdatingReplicaKey = 0;
                                    verCurrent.ullTickCount = 0;
                                    verCreation.dwLastUpdatingReplicaKey = 0;
                                    verCreation.ullTickCount = 0;
                                    dwFlags = SYNC_CHANGE_FLAG_DOES_NOT_EXIST;
                                }

                                if (SUCCEEDED(hr))
                                {
                                    // Add the item to the batch of destination versions.
                                    GUID guidReplicaID = GUID_NULL;
                                    ULONG cbID = sizeof(guidReplicaID);
                                    hr = GetReplicaId((BYTE*)&guidReplicaID, &cbID);
                                    if (SUCCEEDED(hr))
                                    {
                                        hr = pDestChangeBuilder->AddItemMetadata((BYTE*)&guidReplicaID,
                                            (BYTE*)&gidItem, &verCurrent, &verCreation, dwFlags, NULL);
                                    }
                                }
                            }

                            pChange->Release();
                        }
                    }

                    if (FAILED(hrEnum))
                    {
                        hr = hrEnum;                    
                    }

                    pRemoteEnum->Release();                
                }

                if (SUCCEEDED(hr))
                {
                    hr = pDestChangeBuilder->GetChangeEnumerator(ppLocalVersionsEnum);               
                }

                pDestChangeBuilder->Release();
            }

            pProvSvc->Release();        
        }
    }

    return hr;
}

請參閱

參考

IKnowledgeSyncProvider 介面
CONFLICT_RESOLUTION_POLICY 列舉