다음을 통해 공유


방법: 공급자가 메타데이터 스키마를 변경할 때 메타데이터 업그레이드

이 항목에서는 공급자가 메타데이터 스키마를 변경하는 경우 관리되는 언어를 사용하여 Metadata Storage Service 저장소를 업그레이드하는 방법에 대해 설명합니다.

이 항목에서는 기본적인 C# 및 Microsoft .NET Framework 개념에 익숙하다고 가정합니다.

이 항목의 예제에서는 다음과 같은 Sync Framework 클래스 및 인터페이스를 중점적으로 설명합니다.

메타데이터 업그레이드 이해

Metadata Storage Service에서는 소형 데이터베이스에 복제본 및 항목 메타데이터를 저장합니다. 공급자는 개발자가 새 버전의 특정 공급자를 릴리스할 때 변경될 수 있는 데이터베이스의 사용자 지정 필드를 정의할 수 있습니다. Sync Framework에서는 공급자 버전 변경에 따른 메타데이터 저장소 업그레이드를 지원합니다.

메타데이터 저장소 업그레이드는 공급자가 사용하는 사용자 지정 필드가 변경되는 경우에만 필요합니다. 항목 데이터 형식의 변경은 메타데이터 형식에 영향을 주지 않습니다.

공급자는 복제본에 대한 메타데이터를 저장할 때 ProviderVersion을 사용하여 복제본 메타데이터와 호환되는 공급자 버전을 설정합니다. 공급자는 나중에 메타데이터 저장소를 열 때 복제본 메타데이터와 연결되어 있는 공급자 버전을 확인할 수 있습니다. 메타데이터 저장소를 여는 공급자 버전과 메타데이터가 저장된 공급자 버전이 다르면 공급자가 복제본의 메타데이터 스키마를 업그레이드할 수 있습니다.

메타데이터 저장소는 다음 단계를 사용하여 업그레이드됩니다.

  1. SqlSyncMetadataStoreSerializer 개체를 사용하여 복제본 메타데이터를 직렬화합니다.

  2. 메타데이터 저장소에서 복제본 메타데이터를 제거합니다.

  3. 새로운 형식의 복제본 메타데이터가 메타데이터 저장소에 만들어집니다.

  4. 앞에서 직렬화된 복제본 메타데이터를 SqlSyncMetadataStoreSerializer 개체를 사용하여 새로운 형식으로 가져옵니다.

Sync Framework에서 제공하는 IProviderUpgradeCallback이라는 콜백 메커니즘을 사용하여 공급자는 필요한 경우 메타데이터를 변경하는 등 업그레이드 프로세스를 제어할 수 있습니다.

자세한 내용은 메타데이터 저장소 버전 업그레이드를 참조하십시오.

빌드 요구 사항

예제

이 항목의 예제 코드에서는 업그레이드하는 동안 사용자 지정 필드를 추가하는 메타데이터 저장소를 업그레이드하는 방법을 보여 줍니다. IProviderUpgradeCallback을 구현하는 클래스는 메타데이터 저장소에 있는 각 항목의 새 필드 값을 설정하는 데 사용됩니다.

메타데이터 저장소 업그레이드

이 예제에서는 복제본 메타데이터의 현재 공급자 버전이 지정된 값보다 작은 경우 메타데이터 저장소를 업그레이드합니다. 업그레이드의 일부로 추가 사용자 지정 필드가 복제본의 메타데이터 스키마에 추가되고 인덱스 필드로 지정됩니다.

ReplicaMetadata 개체에 대한 모든 참조가 해제되도록 반드시 SqlMetadataStore 개체를 삭제하고 다시 열어야 합니다. 이렇게 하지 않으면 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 버전이 변경될 때 메타데이터 저장소를 업그레이드하는 방법에 대해 자세하게 알아볼 수 있습니다. 자세한 내용은 메타데이터 저장소 버전 업그레이드를 참조하십시오.

메타데이터 저장소를 업그레이드하지 않고 서로 다른 버전의 구성 요소를 상호 운용할 수 있도록 메타데이터 저장소의 정식 형식을 사용하는 방법에 대해서도 자세히 알아볼 수 있습니다. 자세한 내용은 버전이 다른 구성 요소의 메타데이터 액세스를 참조하십시오.

참고 항목

개념

일반적인 표준 사용자 지정 공급자 태스크 프로그래밍
메타데이터 저장소 버전 업그레이드