Partilhar via


Como atualizar metadados quando o provedor altera o esquema de metadados¶

Este tópico descreve como usar uma linguagem gerenciada para atualizar um repositório do serviço de armazenamento de metadados quando o provedor altera o esquema de metadados.

Este tópico pressupõe uma familiaridade básica com os conceitos de C# e Microsoft .NET Framework.

Os exemplos neste tópico se concentram nas seguintes classes e interfaces do Sync Framework:

Noções básicas sobre a atualização de metadados

O serviço de armazenamento de metadados armazena metadados de réplica e de item em um banco de dados leve. Um provedor pode definir campos personalizados no banco de dados que podem ser alterados conforme um desenvolvedor lança novas versões de um provedor específico. O Sync Framework dá suporte à atualização do repositório de metadados devido às alterações de versão do provedor.

Será necessário atualizar o repositório de metadados somente se os campos personalizados usados pelo provedor forem alterados. As alterações de formato dos dados de item não afeta o formato dos metadados.

Quando um provedor armazena metadados para uma réplica, ele define a versão do provedor compatível com os metadados de réplica usando ProviderVersion. Quando um provedor abre posteriormente o repositório de metadados, ele pode verificar a versão do provedor associada aos metadados da réplica. Quando a versão do provedor que abre o repositório de metadados é diferente da versão do provedor armazenada nos metadados, o provedor pode atualizar o esquema de metadados da réplica.

Um repositório de metadados é atualizado executando as etapas a seguir.

  1. Um objeto SqlSyncMetadataStoreSerializer é usado para serializar os metadados da réplica.

  2. Os metadados da réplica são removidos do repositório de metadados.

  3. Os metadados da réplica são criados no novo formato no repositório de metadados.

  4. Os metadados de réplica serializados previamente são importados no novo formato usando o objeto SqlSyncMetadataStoreSerializer.

O Sync Framework fornece um mecanismo de retorno de chamada, IProviderUpgradeCallback, para permitir que o provedor controle o processo de atualização, incluindo as alteração necessárias dos metadados.

Para obter mais informações, consulte Atualizando a versão do repositório de metadados.

Requisitos de compilação

Exemplo

O código de exemplo neste tópico mostra como atualizar um repositório de metadados que adiciona um campo personalizado durante a atualização. Uma classe que implementa IProviderUpgradeCallback é usada para definir o valor do novo campo para cada item no repositório de metadados.

Atualizando o repositório de metadados

Este exemplo atualizará o repositório de metadados quando a versão do provedor atual dos metadados de réplica for menor que o valor especificado. Como parte da atualização, um campo personalizado adicional é adicionado ao esquema de metadados para a réplica e é especificado como um campo de índice.

Esteja ciente de que o objeto SqlMetadataStore deve ser descartado e reaberto de forma que todas as referências ao objeto ReplicaMetadata sejam liberadas. Se isso não for feito, a chamada de RemoveReplicaMetadata lançará 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();
    }
}

Respondendo para atualizar retornos de chamada

Este exemplo define uma classe que implementa a interface IProviderUpgradeCallback. No exemplo anterior, uma instância desta classe é especificada para o método DeserializeReplicaMetadata. O Sync Framework chama os métodos nesta interface para permitir que o provedor controle a atualização e faça as alterações necessárias nos metadados. No método OnProviderUpgradeRequired deste exemplo, a atualização será cancelada se a versão do provedor armazenada atualmente nos metadados da réplica não tiverem o valor esperado. No método OnItemMetadataDeserialized deste exemplo, o valor do novo campo address é definido nos metadados de cada item.

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.");
        }
    }

Próximas etapas

Em seguida, você pode saber mais sobre como atualizar o repositório de metadados quando a versão do Sync Framework for alterada. Para obter mais informações, consulte Atualizando a versão do repositório de metadados.

Você também pode saber mais sobre como usar o formato canônico do repositório de metadados a fim de habilitar componentes de versões diferentes para interoperar sem atualizar o repositório de metadados. Para obter mais informações, consulte Acessando metadados em componentes com versões diferentes.

Consulte também

Conceitos

Programando tarefas comuns do provedor personalizado padrão
Atualizando a versão do repositório de metadados