IKnowledgeSyncProvider::GetChangeBatch
取得變更批次,其中包含目的地提供者之指定知識內未包含之項目的項目中繼資料。
HRESULT GetChangeBatch(
DWORD dwBatchSize,
ISyncKnowledge * pSyncKnowledge,
ISyncChangeBatch ** ppSyncChangeBatch,
IUnknown ** ppUnkDataRetriever);
參數
- dwBatchSize
[in] 要求要包含在此變更批次內的變更數目。
- pSyncKnowledge
[in] 目的地提供者的知識。您必須先針對來源知識呼叫 ISyncKnowledge::MapRemoteToLocal 來對應這個知識,然後才能將它用於變更列舉。
- ppSyncChangeBatch
[out] 傳回包含 pSyncKnowledge 中未包含項目之項目中繼資料的變更批次。
- ppUnkDataRetriever
[out] 傳回可用來擷取變更資料的物件。它可以是 ISynchronousDataRetriever 物件或提供者特有的物件。
傳回值
S_OK
提供者決定的錯誤碼
備註
請注意,dwBatchSize 只是要求的數目,可能會傳回較小或較大的批次。
實作者注意事項
如果這個批次之後沒有其他變更要傳送,就必須在傳回的變更批次上呼叫 ISyncChangeBatchBase::SetLastBatch。否則,Sync Framework 會再次呼叫 GetChangeBatch 來擷取另一個變更批次。
範例
下列範例是 GetChangeBatch 的實作。第一個範例示範如何從自動中繼資料存放區物件取得變更批次,以及從自訂項目存放區物件取得資料擷取介面。第二個範例會實作第一個範例中所呼叫的 m_pMetadataMgr->GetChangeBatch
方法。此方法會列舉中繼資料存放區中的所有項目,然後如果項目未包含於目的地知識中,就將該項目加入至傳回的變更批次中。
STDMETHODIMP CXMLProvider::GetChangeBatch(
DWORD dwBatchSize,
ISyncKnowledge * pSyncKnowledge,
ISyncChangeBatch ** ppSyncChangeBatch,
IUnknown ** ppUnkDataRetriever)
{
HRESULT hr = E_UNEXPECTED;
if (NULL == pSyncKnowledge || NULL == ppSyncChangeBatch || NULL == ppUnkDataRetriever)
{
hr = E_POINTER;
}
else
{
_ASSERT(NULL != m_pMetadataMgr);
hr = m_pMetadataMgr->GetChangeBatch(dwBatchSize, pSyncKnowledge, ppSyncChangeBatch);
if (SUCCEEDED(hr))
{
hr = m_pItemStore->QueryInterface(IID_IUnknown, (void**)ppUnkDataRetriever);
}
}
return hr;
}
STDMETHODIMP CMetadataMgr::GetChangeBatch(
DWORD dwBatchSize,
ISyncKnowledge *pSyncKnowledge,
ISyncChangeBatch ** ppSyncChangeBatch)
{
HRESULT hr = E_UNEXPECTED;
ISyncChangeBatch* pChangeBatch = NULL;
ISyncKnowledge* pMappedDestKnowledge = NULL;
ISyncKnowledge* pSourceKnowledge = NULL;
if (NULL == pSyncKnowledge || NULL == ppSyncChangeBatch)
{
hr = E_POINTER;
}
else
{
// Get our (source) knowledge object, map the remote (destination) knowledge for local use,
// and get our replica ID.
GUID guidReplicaID;
hr = GetKnowledge(&pSourceKnowledge);
if (SUCCEEDED(hr))
{
hr = pSourceKnowledge->MapRemoteToLocal(pSyncKnowledge, &pMappedDestKnowledge);
if (SUCCEEDED(hr))
{
ULONG cbID = sizeof(guidReplicaID);
hr = GetReplicaId((BYTE*)&guidReplicaID, &cbID);
}
}
if (SUCCEEDED(hr))
{
// Create a new change batch object. We'll fill this object with changes to send.
IProviderSyncServices* pProvSvc = NULL;
// This helper function creates and initializes the IProviderSyncServices interface.
hr = GetProviderSyncServices(&c_idParams, &pProvSvc);
if (SUCCEEDED(hr))
{
hr = pProvSvc->CreateChangeBatch(pSyncKnowledge, NULL, &pChangeBatch);
pProvSvc->Release();
pProvSvc = NULL;
}
}
// Enumerate the items in our store and add new changes to the change batch.
if (SUCCEEDED(hr))
{
// Begin an unordered group in our change batch. All change items will be added to this group.
hr = pChangeBatch->BeginUnorderedGroup();
if (SUCCEEDED(hr))
{
ULONG cFetched = 1;
IItemMetadata* pItemMeta = NULL;
SYNC_GID gidItem;
ULONG cbgid = sizeof(gidItem);
SYNC_VERSION verCur;
SYNC_VERSION verCreate;
hr = Reset();
while (S_OK == hr)
{
hr = Next(1, &pItemMeta, &cFetched);
if (S_OK == hr)
{
hr = pItemMeta->GetGlobalId((BYTE*)&gidItem, &cbgid);
if (SUCCEEDED(hr))
{
hr = pItemMeta->GetChangeVersion(&verCur);
if (SUCCEEDED(hr))
{
// Find out whether the destination already knows about this change.
hr = pMappedDestKnowledge->ContainsChange((BYTE*)&guidReplicaID,
(BYTE*)&gidItem, &verCur);
if (S_FALSE == hr)
{
// S_FALSE means the destination does not know about the
// change, so add it to the change batch.
DWORD dwFlags = 0;
BOOL fTomb = 0;
hr = pItemMeta->GetIsDeleted(&fTomb);
if (fTomb)
{
dwFlags = SYNC_CHANGE_FLAG_DELETED;
}
hr = pItemMeta->GetCreationVersion(&verCreate);
if (SUCCEEDED(hr))
{
hr = pChangeBatch->AddItemMetadataToGroup((BYTE*)&guidReplicaID,
(BYTE*)&gidItem, &verCur, &verCreate, dwFlags, 0, NULL);
}
}
}
}
pItemMeta->Release();
}
}
}
if (SUCCEEDED(hr))
{
// We always send the entire set of changes, so every batch is the last batch.
// If this flag is not set Sync Framework will call GetChangeBatch again.
hr = pChangeBatch->SetLastBatch();
}
if (SUCCEEDED(hr))
{
// Close the change batch group that contains our changes.
hr = pChangeBatch->EndUnorderedGroup(pSourceKnowledge, TRUE);
}
}
if (NULL != pChangeBatch)
{
if (SUCCEEDED(hr))
{
// Return the change batch we've constructed. This will be sent to the
// destination provider.
*ppSyncChangeBatch = pChangeBatch;
}
else
{
pChangeBatch->Release();
}
}
if (NULL != pMappedDestKnowledge)
{
pMappedDestKnowledge->Release();
}
if (NULL != pSourceKnowledge)
{
pSourceKnowledge->Release();
}
}
return hr;
}