Поделиться через


Применение изменений

После того как поставщик назначения получит пакет изменений и разрешит конфликты, необходимо применить изменения в реплике назначения. Обычно это выполняется поставщиком назначения в рамках метода ProcessChangeBatch (для управляемого кода) или метода ProcessChangeBatch (для неуправляемого кода) и проще всего осуществляется с помощью объекта применения изменений, предоставляемого платформой Sync Framework. 

Порядок применения изменений

После того как поставщик назначения получает пакет изменений от поставщика источника, поставщик назначения применяет изменений в реплике назначения. Объект применения изменений, предоставляемый платформой Sync Framework, можно получить путем создания объекта NotifyingChangeApplier (для управляемого кода) или вызова метода IProviderSyncServices::CreateChangeApplier (для неуправляемого кода). Метод ApplyChanges (для управляемого кода) или метод ApplyChanges (для неуправляемого кода) обнаруживает конфликты и вызывает методы в поставщике назначения для применения изменений в реплике назначения.

Обработка элемента изменения

Для обработки типичного элемента изменения объект применения изменений сначала вызывает метод LoadChangeData (для управляемого кода) или метод ISynchronousDataRetriever::LoadChangeData (для неуправляемого кода) в поставщике источника, чтобы запустить передачу данных. Этот метод возвращает объект object (для управляемого кода) или интерфейс IUnknown (для неуправляемого кода), который представляет механизм передачи данных. Затем объект применения изменений вызывает метод SaveItemChange (для управляемого кода) или метод ISynchronousNotifyingChangeApplierTarget::SaveChange (для неуправляемого кода) в поставщике назначения и передает объект передачи данных в составе контекста сохранения изменений. Затем поставщик назначения может передать данные в реплику назначения. Сведения о любых ошибках, произошедших при получении данных или обработке изменений, передаются с помощью метода RecordRecoverableErrorForItem (для управляемого кода) или метода ISaveChangeContext::SetRecoverableErrorOnChange (для неуправляемого кода). Этот метод записывает устранимую ошибку для этого элемента в объект набора известных знаний, который содержится в пакете изменений. В качестве альтернативы (при использовании конфликтов ограничений) можно создать отчет о конфликте ограничений, вызвав RecordConstraintConflictForItem (для управляемого кода) или ISaveChangeContext2::SetConstraintConflictOnChange (для неуправляемого кода). После этого конфликт ограничений может быть разрешен, как указано приложением или поставщиком.

Обновление набора известных знаний

Во время применения изменений объект применения изменений обновляет набор известных знаний, содержащийся в пакете изменений. Набор известных знаний представляет собой набор знаний реплики источника, спроецированный на изменения в пакете изменений, и содержит данные, которые станут известны реплике назначения после применения всех изменений из пакета изменений. Набор известных знаний обновляется следующими способами.

  • Если было применено только подмножество изменений из-за прерывания или отмены операций, объект применения изменений использует операцию project, чтобы ограничить набор знаний только множеством примененных изменений.

  • Если не удалось применить некоторые изменения, объект применения изменений также исключает их из набора знаний.

Учтите, что в реализации службы не нужно вручную выполнять операции project, union и exclude. Объект применения изменений выполняет эти операции от имени службы.

Сохранение обновленного набора знаний назначения

После обновления набора известных знаний он объединяется с набором знаний реплики назначения. Поставщик назначения должен атомарным образом заменить набор знаний реплики назначения обновленным набором. Атомарность достигается за счет того, что обновленный набор знаний сохраняется только один раз для пакета, если все изменения в пакете применены в рамках одной транзакции. Объект применения изменений участвует в этом процессе, вызывая метод StoreKnowledgeForScope (для управляемого кода) или метод ISynchronousNotifyingChangeApplierTarget::SaveKnowledge (для неуправляемого кода) в поставщике назначения в конце каждого пакета. Набор знаний, передаваемый этому методу, является обновленным набором знаний, который необходимо применить к реплике назначения. В качестве альтернативы поставщик назначения может вызвать метод GetUpdatedDestinationKnowledge (для управляемого кода) или метод ISaveChangeContext::GetKnowledgeForScope (для неуправляемого кода), чтобы получить обновленный набор знаний.

Если поставщики используют базовые единицы для представления подэлементов, процесс применения изменений выглядит несколько иначе. Дополнительные сведения см. в разделе Синхронизация базовых единиц.

Особые вопросы использования иерархических реплик

Синхронизация иерархических реплик может вызвать определенные сложности, возникающие в результате разбиения наборов изменений на пакеты для передачи от источника к назначению. Платформа Sync Framework не поддерживает иерархические принципы организации данных. Поэтому задача разрешения таких ситуаций полностью решается поставщиками.

Наиболее распространенной трудностью является порядок связей между родителями и потомками в операциях обновления. Например, рассмотрим следующий сценарий.

  1. В реплике источника создана новая папка и набор новых элементов в этой папке.

  2. Поставщик назначения запрашивает изменения от поставщика источника. Поставщик источника отправляет список изменений в виде двух пакетов. Однако пакет изменений, содержащий создание родительской папки, прибывает в назначение позже, чем пакет, содержащий дочерние элементы.

  3. Поставщик назначения должен принять решение, где хранить набор элементов, полученных в первом пакете, поскольку место их хранения будет неизвестно до получения второго пакета.

Сокращение числа обновлений иерархических данных

Если выполняются обновления, самым простым способом снизить сложность связей типа «родители-потомки» является упорядочение глобальных идентификаторов в поставщике источника. В результате родительские элементы всегда будут прибывать в назначение раньше, чем их дочерние элементы.

Когда поставщики назначения работают с передачей обновлений, выполняемых в хранилище иерархических данных, они могут получить связи типа «родители-потомки», нарушающие порядок. Поставщики назначения должны иметь возможность разрешить такую ситуацию, удалив изменение, нарушающее порядок, и записав исключение в наборе знаний либо поставив изменение в очередь для дальнейшего применения. Поскольку элементы могут иметь большой размер, удаление изменение и запись исключений в набор знаний будет, вероятнее всего, самым эффективным методом.

Сокращение числа удалений иерархических данных

Поставщики назначения определяют, является ли элемент контейнером. Для пустых контейнеров удаление выполняется немедленно. Однако, если контейнер содержит элементы, которые не были помечены к удалению, поставщик может выполнить одно из следующих действий.

  • Поставить операции удаления в очередь для дальнейшей обработки. После того как все дочерние элементы в контейнере будут помечены к удалению, можно запустить фактическое удаление.

  • Удалить данный запрос и занести исключение в набор знаний, чтобы указать, что получен элемент, нарушающий порядок.

Для работы со сценариями, где в иерархии удаляется родительский узел, а затем добавляется дочерний, применяется следующее правило: операции удаления, помещенные в очередь, действительны только до конца сеанса между парой поставщиков и не сохраняются при смене участников.

См. также

Справочник

NotifyingChangeApplier

StoreKnowledgeForScope

IChangeDataRetriever

SaveChangeContext

Другие ресурсы

Реализация стандартного пользовательского поставщика

Интерфейс ISynchronousNotifyingChangeApplier

ISynchronousNotifyingChangeApplierTarget::SaveKnowledge

Интерфейс ISynchronousDataRetriever

Интерфейс ISaveChangeContext