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


Как обновить метаданные при изменении поставщиком схемы метаданных

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

Материал этого раздела предполагает, что читатель владеет основными понятиями языка C# и платформы Microsoft .NET Framework.

В примерах, приведенных в этом разделе, обсуждаются следующие классы и интерфейсы платформы Sync Framework.

Основные сведения об обновлении метаданных

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

Обновление хранилища метаданных необходимо только при изменении пользовательских полей, используемых поставщиком. Изменение до формата данных элемента не затрагивает формат метаданных.

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

Хранилище метаданных обновляется с помощью выполнения следующих шагов.

  1. Объект SqlSyncMetadataStoreSerializer используется для сериализации метаданных реплики.

  2. Метаданные реплики удаляются из хранилища метаданных.

  3. В хранилище метаданных создаются метаданные реплики в новом формате.

  4. Ранее сериализованные метаданные реплики импортируются в новый формат с помощью объекта SqlSyncMetadataStoreSerializer.

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

Дополнительные сведения см. в разделе Обновление версии хранилища метаданных.

Требования построения

Примеры

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

Обновление хранилища метаданных

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

Помните, что объект SqlMetadataStore необходимо удалить и повторно открыть для освобождения всех ссылок на объект ReplicaMetadata. Если этого не сделать, вызов метода RemoveReplicaMetadata вызывает исключение ReplicaMetadataInUseException.

public static void UpgradeMetadataStore(SqlMetadataStore store, string storePath,
    SortedList<SyncId, Contact> contactList)
{
    // Get the provider version and replica ID from the metadata store.
    uint providerVersion = store.GetSingleReplicaMetadata().ProviderVersion;
    SyncId replicaId = store.GetSingleReplicaMetadata().ReplicaId;

    // Check the provider version of the metadata store and upgrade if necessary.
    if (providerVersion < (uint)ContactsProviderVersion.ContactsProvider_v2)
    {
        // Dispose the store to release all references to the replica metadata
        // or the call to RemoveReplicaMetadata will throw ReplicaMetadataInUseException.
        store.Dispose();
        store = null;

        // Reopen the store.
        store = SqlMetadataStore.OpenStore(storePath);

        // Start a transaction.
        store.BeginTransaction();

        // Serialize the metadata store in canonical format.
        string serializedName = "SerializedStoreForUpgrade.dat";
        SyncMetadataStoreSerializer mdsSerializer = store.GetMetadataStoreSerializer();
        mdsSerializer.SerializeReplicaMetadata(ContactStore.ContactIdFormatGroup, replicaId,
            serializedName, CompatibilityLevel.SyncFrameworkVersion1);
        
        // Remove the replica metadata from the store.
        store.RemoveReplicaMetadata(ContactStore.ContactIdFormatGroup, replicaId);

        // Initialize replica metadata, adding a new index column for Address.

        // Create custom fields for First Name, Last Name, Phone Number. These will be used
        // as unique index fields for identifying items between the metadata store and the item store.
        // Also include a custom field for Address, which will be used as an index.
        FieldSchema[] CustomFields = 
        {
            new FieldSchema(FirstNameField, typeof(string), 100),
            new FieldSchema(LastNameField, typeof(string), 100),
            new FieldSchema(PhoneNumberField, typeof(string), 20),
            new FieldSchema(AddressField, typeof(string), 100)
        };

        // Specify the index fields.
        string[] IndexFields = { FirstNameField, LastNameField, PhoneNumberField };
        IndexSchema[] Indexes = 
        {
            new IndexSchema(IndexFields, true),
            new IndexSchema(AddressField, false)
        };

        // Create the metadata for the replica in the metadata store.
        ReplicaMetadata newRepMeta = store.InitializeReplicaMetadata(
            ContactIdFormatGroup, replicaId, CustomFields, Indexes);

        // Import the serialized metadata.
        ContactsProviderUpgrader upgrader = new ContactsProviderUpgrader(contactList);
        mdsSerializer.DeserializeReplicaMetadata(serializedName, (uint)ContactsProviderVersion.ContactsProvider_v2,
            upgrader);

        // Set the new provider version.
        newRepMeta.ProviderVersion = (uint)ContactsProviderVersion.ContactsProvider_v2;

        newRepMeta.SaveReplicaMetadata();

        // Commit the transaction.
        store.CommitTransaction();
    }
}

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

В этом примере определяется класс, реализующий интерфейс IProviderUpgradeCallback. В предыдущем примере экземпляр этого класса указывается в методе DeserializeReplicaMetadata. Платформа Sync Framework вызывает методы в этом интерфейсе, чтобы дать возможность поставщику управлять обновлением и сделать необходимые изменения в метаданных. В этом примере в методе OnProviderUpgradeRequired обновление отменяется, если версия поставщика, в настоящее время хранящегося в метаданных реплики, не совпадает с указанным значением. В методе OnItemMetadataDeserialized этого примера значение нового поля address задается в метаданных для всех элементов.

class ContactsProviderUpgrader : IProviderUpgradeCallback
{
    // The contact list is the item store. Save it so new metadata fields can be updated
    // during the upgrade.
    public ContactsProviderUpgrader(SortedList<SyncId, Contact> contactList) 
    {
        _contactList = contactList;
    }

    private SortedList<SyncId, Contact> _contactList;

    #region IProviderUpgradeCallback Members

    public void OnCustomReplicaMetadataDeserialized(byte[] customReplicaMetadata)
    {
        // This replica doesn't store custom replica metadata, so there's nothing to do!
    }

    public void OnItemMetadataDeserialized(ItemMetadata itemMetadata, Dictionary<string, SyncFieldValue> extraFields)
    {
        // The address field is new in the upgrade, so set it now from the contact list.
        Contact contact = _contactList[itemMetadata.GlobalId];
        itemMetadata.SetCustomField(ContactStore.AddressField, contact.Address);
    }

    public void OnProviderUpgradeRequired(uint dwCurrentProviderVersionInFile)
    {
        // This upgrader can only upgrade from provider version 1.
        if ((uint)ContactsProviderVersion.ContactsProvider_v1 != dwCurrentProviderVersionInFile)
        {
            throw new MetadataStoreProviderVersionMismatchException("Can't upgrade the metadata store from the specified version.");
        }
    }

Следующие шаги

Далее необходимо больше узнать об обновлении хранилища метаданных при изменении версии платформы Sync Framework. Дополнительные сведения см. в разделе Обновление версии хранилища метаданных.

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

См. также

Основные положения

Программирование типовых задач стандартных пользовательских поставщиков
Обновление версии хранилища метаданных