Condividi tramite


IKnowledgeSyncProvider::ProcessChangeBatch

Elabora un set di modifiche per la rilevazione di conflitti e l'applicazione di modifiche all'archivio di elementi.

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

Parametri

  • resolutionPolicy
    [in] Criteri di risoluzione dei conflitti da utilizzare quando le modifiche vengono applicate da questo metodo.
  • pSourceChangeBatch
    [in] Batch di modifiche del provider di origine da applicare in locale.
  • pUnkDataRetriever
    [in] Oggetto che può essere utilizzato per recuperare i dati di modifica. Può essere un oggetto ISynchronousDataRetriever o un oggetto specifico del provider.
  • pCallback
    [in] Oggetto che riceve notifiche degli eventi durante l'applicazione delle modifiche.
  • pSyncSessionStatistics
    [in, out] Registra le statistiche relative alle modifiche. Per un provider che utilizza l'applicazione personalizzata delle modifiche, è necessario aggiornare questo oggetto con i risultati dell'applicazione delle modifiche.

Valore restituito

  • S_OK

  • Codici di errore determinati dal provider

Osservazioni

Quando una modifica di origine contiene modifiche delle unità di modifica, il provider di destinazione deve determinare quali versioni delle unità di modifica, se disponibili, includere nel batch di versioni di destinazione inviato all'oggetto di applicazione modifiche. La decisione dipende dal tipo di modifica rispetto al provider di origine e dal fatto che l'elemento sia stato contrassegnato o meno per l'eliminazione nella replica di destinazione. Per ulteriori informazioni, vedere Sincronizzazione delle unità di modifica.

Esempio

Negli esempi seguenti viene illustrato come implementare ProcessChangeBatch. Nel primo esempio viene illustrato come creare un oggetto ISynchronousNotifyingChangeApplier e chiamare ISynchronousNotifyingChangeApplier::ApplyChanges per applicare le modifiche alla replica di destinazione. Nel secondo esempio viene implementato il metodo m_pMetadataMgr->GetItemBatchVersions utilizzato nel primo esempio. Questo metodo enumera le modifiche contenute nel batch di modifiche di origine e crea un elenco corrispondente di versioni di destinazione tramite un oggetto 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;
}

Vedere anche

Riferimento

Interfaccia IKnowledgeSyncProvider
Enumerazione CONFLICT_RESOLUTION_POLICY