列挙された変更単位をフィルター選択する方法

このトピックでは、カスタム データ ストアからのデータを同期する Sync Framework 同期プロバイダーによって列挙された変更単位を、マネージ言語を使用してフィルター選択する方法について説明します。

このトピックは、C# および Microsoft .NET Framework の概念について基本的な知識がある方を対象としています。

このトピックの例では、次に示す Sync Framework のクラスとメンバーを中心に説明します。

変更単位のフィルター選択について

変更単位フィルターは、同期対象のデータを一部の変更単位に限定します。たとえば、連絡先の名前フィールドと電話番号フィールドだけを同期し、その他の変更単位は無視する場合などに使用します。スコープ内の項目に定義されている変更単位の一部分だけをレプリカに保存するような場合、変更単位フィルターが効果的です。

Sync Framework は、変更列挙に含める変更単位の一覧を定義するために、ChangeUnitListFilterInfo オブジェクトを提供しています。同期アプリケーションは適切なメカニズムを自由に使ってプロバイダーと同期アプリケーション間にフィルターを設定できます。フィルターを 2 つのプロバイダー間でネゴシエートすることもできます。フィルターのネゴシエーションの詳細については、「同期データのフィルター設定」を参照してください。

変更単位フィルターが定義されていると、Sync Framework は同期元プロバイダーの LoadChangeData を呼び出すときに、フィルターに含まれる変更単位のデータのみを要求します。

同期先のプロバイダーは標準の変更バッチの場合と同様に変更を受け取り適用しますが、SaveChangeWithChangeUnits に送られるデータには、フィルターで選択された変更単位のみが含められます。

ビルド要件

このトピック内のコード例は、Metadata Storage Service を使用して、含められる変更単位をフィルターする変更バッチを作成する方法を示します。この例のレプリカは、連絡先情報がコンマ区切りの値の一覧として保存されているテキスト ファイルです。同期する項目は、このファイルに含まれる連絡先です。フィルターは連絡先の中の名前フィールドと電話番号フィールドのみを含めるように定義されています。

フィルターの設定

同期元プロバイダーは、変更を列挙するときにどの連絡先フィールドを変更単位に含めるかをアプリケーションが設定できるようにするためのパブリック メソッドを実装します。

public void SetContactFieldsToInclude(Contact.ChangeUnitFields[] includedFields)
{
    // Translate the array of fields to a list of IDs.
    _includedChangeUnits = new List<SyncId>(includedFields.Length);
    for (int iField = 0; iField < includedFields.Length; iField++)
    {
        _includedChangeUnits.Add(new SyncId((byte)includedFields[iField]));
    }

    _isFiltered = true;
}

同期アプリケーションは同期元プロバイダーをローカル プロバイダーとして作成し、SetContactFieldsToInclude メソッドを使って名前フィールドと電話番号フィールドのみが変更の列挙に含められるように指定します。同期アプリケーションは同期先プロバイダーも作成して、同期を実行します。

private void SynchronizeWithChangeUnitFiltering(ContactStore localStore, ContactStore remoteStore, SyncDirectionOrder syncDir)
{
    // Create the local provider and set the change unit filter.
    // The filter is ignored when the provider is the destination provider.
    SyncProvider localProvider = new ContactsProviderChangeUnitFiltering(localStore);
    // Only include name and phone number fields.
    Contact.ChangeUnitFields[] includedFields = new Contact.ChangeUnitFields[2];
    includedFields[0] = Contact.ChangeUnitFields.NameCU;
    includedFields[1] = Contact.ChangeUnitFields.PhoneCU;
    ((ContactsProviderChangeUnitFiltering)localProvider).SetContactFieldsToInclude(includedFields);
    
    // Create the remote provider and do not set a filter.
    SyncProvider remoteProvider = new ContactsProviderChangeUnitFiltering(remoteStore);

    // Create the synchronization orchestrator and set the providers and synchronization direction.
    SyncOrchestrator orchestrator = new SyncOrchestrator();
    orchestrator.LocalProvider = localProvider;
    orchestrator.RemoteProvider = remoteProvider;
    orchestrator.Direction = syncDir;

    string msg;
    try
    {
        // Synchronize data between the two providers.
        SyncOperationStatistics stats = orchestrator.Synchronize();

        // Display statistics for the synchronization operation.
        msg = "Synchronization succeeded!\n\n" +
            stats.DownloadChangesApplied + " download changes applied\n" +
            stats.DownloadChangesFailed + " download changes failed\n" +
            stats.UploadChangesApplied + " upload changes applied\n" +
            stats.UploadChangesFailed + " upload changes failed";
    }
    catch (Exception ex)
    {
        msg = "Synchronization failed! Here's why: \n\n" + ex.Message;
    }
    MessageBox.Show(msg, "Synchronization Results");
}

フィルターされた変更バッチの列挙

同期元プロバイダーは GetChangeBatch を実装して、フィルターが指定されたら、フィルターされた変更バッチを作成するときに Metadata Storage Service を使用できるようにします。これは、ChangeUnitListFilterInfo オブジェクトを作成して、含める変更単位を指定したリストで初期化することによって可能になります。フィルターの情報は ReplicaMetadata オブジェクトの GetFilteredChangeBatch メソッドに渡されます。メタデータ ストレージ サービスは、プロバイダーをコールバックしてフィルターに何が含まれているかを確認する必要がないので、null が filterCallback パラメーターに指定されます。

public override ChangeBatch GetChangeBatch(uint batchSize, SyncKnowledge destinationKnowledge, out object changeDataRetriever)
{
    // Return this object as the IChangeDataRetriever object that is called to retrieve item data.
    changeDataRetriever = this;

    ChangeBatch retrievedBatch;
    if (_isFiltered)
    {
        // Use the metadata storage service to get a filtered batch of changes.
        ChangeUnitListFilterInfo filterInfo = new ChangeUnitListFilterInfo(IdFormats, _includedChangeUnits, true);
        retrievedBatch = _ContactStore.ContactReplicaMetadata.GetFilteredChangeBatch(batchSize, destinationKnowledge,
            filterInfo, null);
    }
    else
    {
        // Use the metadata storage service to get a batch of changes.
        retrievedBatch = _ContactStore.ContactReplicaMetadata.GetChangeBatch(batchSize, destinationKnowledge);
    }
    
    return retrievedBatch;
}

次の手順

次は、フィルター ネゴシエーションをプロバイダーに追加して、変更列挙にどのフィルターを使用するかを同期先プロバイダーと通信して決定できるようにします。フィルターのネゴシエーションの詳細については、「フィルター ネゴシエーションの方法」を参照してください。

参照

概念

標準のカスタム プロバイダーをプログラミングするための一般的なタスク
同期データのフィルター設定