//Update the metadata store with changes that have occured on the data store since the last time it was updated. public void UpdateMetadataStoreWithLocalChanges() { SyncVersion newVersion = new SyncVersion(0, _metadata.GetNextTickCount()); _metadata.DeleteDetector.MarkAllItemsUnreported(); foreach (Guid id in _store.Ids) { ItemData data = _store.Get(id); ItemMetadata item = null; //Look up an item's metadata by its ID... item = _metadata.FindItemMetadataById(new SyncId(id)); if (null == item) { //New item, must have been created since that last time the metadata was updated. //Create the item metadata required for sync (giving it a SyncID and a version, defined to be a DWORD and a ULONGLONG //For creates, simply provide the relative replica ID (0) and the tick count for the provider (ever increasing) item = _metadata.CreateItemMetadata(new SyncId(id), newVersion); item.ChangeVersion = newVersion; SaveItemMetadata(item, data.TimeStamp); _syncItemCount++; } else { if (data.TimeStamp > item.GetUInt64Field(TIMESTAMP_COLUMNNAME)) // the item has changed since the last sync operation. { //Changed Item, this item has changed since the last time the metadata was updated. //Assign a new version by simply stating "who" modified this item (0 = local/me) and "when" (tick count for the store) item.ChangeVersion = newVersion; SaveItemMetadata(item, data.TimeStamp); _syncItemCount++; } else { //Unchanged item, nothing has changes so just mark it as live so that the metadata knows it has not been deleted. _metadata.DeleteDetector.ReportLiveItemById(new SyncId(id)); } } } //Now go back through the items that are no longer in the store and mark them as deleted in the metadata. //This sets the item as a tombstone. foreach (ItemMetadata item in _metadata.DeleteDetector.FindUnreportedItems()) { item.MarkAsDeleted(newVersion); SaveItemMetadata(item, 0); // set timestamp to 0 for tombstones } }
internal ItemMetadata CreateItemMetadata(SyncId syncId = null, SyncVersion newVersion = null) { var setChangeVersion = false; if (newVersion == null || syncId == null) { newVersion = new SyncVersion(0, _metadata.GetNextTickCount()); syncId = new SyncId(new SyncGlobalId(0, Guid.NewGuid())); setChangeVersion = true; } var result = _metadata.CreateItemMetadata(syncId, newVersion); if (setChangeVersion) { result.ChangeVersion = newVersion; } return(result); }
public void SaveItemChange(SaveChangeAction saveChangeAction, ItemChange change, SaveChangeContext context) { ItemMetadata item = null; T data = default(T); try { switch (saveChangeAction) { case SaveChangeAction.Create: try { //Do duplicate detection here item = _metaData.FindItemMetadataById(change.ItemId); if (item != null) { throw new SyncProviderException("SaveItemChange must not have Create action for existing items."); } item = _metaData.CreateItemMetadata(change.ItemId, change.CreationVersion); item.ChangeVersion = change.ChangeVersion; data = ConvertFromTransferData(context.ChangeData); CreateDataItem(change, item, data); SaveItemMetadata(item); } catch (Exception e) { throw new SyncProviderException(e, SaveChangeAction.Create); } break; case SaveChangeAction.UpdateVersionAndData: case SaveChangeAction.UpdateVersionOnly: try { item = _metaData.FindItemMetadataById(change.ItemId); if (null == item) { throw new SyncProviderException("Item Not Found in Store!?"); } item.ChangeVersion = change.ChangeVersion; if (saveChangeAction == SaveChangeAction.UpdateVersionOnly) { SaveItemMetadata(item); } else //Also update the data. { data = ConvertFromTransferData(context.ChangeData); UpdateDataItem(change, item, data); SaveItemMetadata(item); } } catch (Exception e) { throw new SyncProviderException(e, SaveChangeAction.UpdateVersionAndData); } break; case SaveChangeAction.DeleteAndStoreTombstone: try { item = _metaData.FindItemMetadataById(change.ItemId); if (null == item) { item = _metaData.CreateItemMetadata(change.ItemId, change.CreationVersion); } if (change.ChangeKind == ChangeKind.Deleted) { item.MarkAsDeleted(change.ChangeVersion); } else { // This should never happen in Sync Framework V1.0 throw new SyncProviderException("Invalid ChangeType"); } item.ChangeVersion = change.ChangeVersion; SaveItemMetadata(item); DeleteDataItem(change, item, data); //item.GlobalId.GetGuidId()); } catch (Exception e) { throw new SyncProviderException(e, SaveChangeAction.DeleteAndStoreTombstone); } break; //Merge the changes! (Take the data from the local item + the remote item),noting to update the tick count to propagate the resolution! case SaveChangeAction.UpdateVersionAndMergeData: try { item = _metaData.FindItemMetadataById(change.ItemId); if (null == item) { throw new SyncProviderException("Item Not Found in Store!?"); } if (item.IsDeleted != true) { //Note - you must update the change version to propagate the resolution! item.ChangeVersion = new SyncVersion(0, _metaData.GetNextTickCount()); //Combine the conflicting data... T dataItem = GetDataItem(item); if (dataItem == null) { throw new SyncProviderException("data item not found for merge"); } data = ConvertFromTransferData(context.ChangeData); data = MergeDataItem(dataItem, data); UpdateDataItem(change, item, data); SaveItemMetadata(item); } } catch (Exception e) { throw new SyncProviderException(e, SaveChangeAction.UpdateVersionAndMergeData); } break; case SaveChangeAction.DeleteAndRemoveTombstone: try { item = _metaData.FindItemMetadataById(change.ItemId); if (item != null) { _metaData.RemoveItemMetadata(new SyncId[] { item.GlobalId }); } data = ConvertFromTransferData(context.ChangeData); DeleteDataItem(change, item, data); } catch (Exception e) { throw new SyncProviderException(e, SaveChangeAction.DeleteAndRemoveTombstone); } break; } } catch (SyncProviderException e) { Exception exception = e.InnerException != null ? e.InnerException : e; string itemDescr = e.SaveChangeAction.ToString(); string errDescr = e.Message + "[" + e.InnerException != null?e.InnerException.ToString() : string.Empty + "]"; RecoverableErrorData recoverableError = new RecoverableErrorData(exception, itemDescr, errDescr); context.RecordRecoverableErrorForItem(recoverableError); } }
//Update the metadata store with changes that have occured on the data store since the last time it was updated. public void UpdateMetadataStoreWithLocalChanges() { SyncVersion newVersion = new SyncVersion(0, _metadata.GetNextTickCount()); _metadata.DeleteDetector.MarkAllItemsUnreported(); var entities = _syncContext.GetSyncObjects(CompanyId, StoreId); foreach (ISyncDataObject entity in entities) { try { ISyncDataObject data = entity; ItemMetadata item = null; //Look up an item's metadata by its ID... item = _metadata.FindItemMetadataById(new SyncId(entity.SyncItemId)); if (null == item) { //New item, must have been created since that last time the metadata was updated. //Create the item metadata required for sync (giving it a SyncID and a version, defined to be a DWORD and a ULONGLONG //For creates, simply provide the relative replica ID (0) and the tick count for the provider (ever increasing) item = _metadata.CreateItemMetadata(new SyncId(entity.SyncItemId), newVersion); item.ChangeVersion = newVersion; SaveItemMetadata(item, BitConverter.ToUInt64(data.SyncItemVersion, 0)); //var package = data as SyncDataPackage; //if (package != null) //{ // item.SetCustomField(PACKAGECOUNT, (UInt32)package.Items.Count); //} } else { //var package = data as SyncDataPackage; //var packageCount = item.GetUInt32Field(PACKAGECOUNT); if (BitConverter.ToUInt64(data.SyncItemVersion, 0) != item.GetUInt64Field(TIMESTAMP_COLUMNNAME)) // the item has changed since the last sync operation. { //Changed Item, this item has changed since the last time the metadata was updated. //Assign a new version by simply stating "who" modified this item (0 = local/me) and "when" (tick count for the store) item.ChangeVersion = newVersion; SaveItemMetadata(item, BitConverter.ToUInt64(data.SyncItemVersion, 0)); } else { //Unchanged item, nothing has changes so just mark it as live so that the metadata knows it has not been deleted. _metadata.DeleteDetector.ReportLiveItemById(new SyncId(entity.SyncItemId)); } } } catch (Exception ex) { Console.WriteLine(ex.Message); } } //Now go back through the items that are no longer in the store and mark them as deleted in the metadata. //This sets the item as a tombstone. foreach (ItemMetadata item in _metadata.DeleteDetector.FindUnreportedItems()) { item.MarkAsDeleted(newVersion); SaveItemMetadata(item, 0); // set timestamp to null for tombstones } }