如何筛选枚举的变更单位

本主题说明如何使用托管语言筛选 Sync Framework 同步提供程序(它同步自定义数据存储区的数据)枚举的变更单位。

本主题假定您基本熟悉 C# 和 Microsoft .NET Framework 概念。

本主题中的示例着重介绍以下 Sync Framework 类和成员:

了解变更单位筛选

变更单位筛选器将同步数据限制为变更单位的子集,例如限制为只同步联系人的姓名和电话号码字段,而忽略其余的变更单位。在副本只存储在作用域中为项定义的变更单位的子集时,变更单位筛选器会很有用。

Sync Framework 提供 ChangeUnitListFilterInfo 对象来定义要在变更枚举中包括的变更单位列表。筛选器可由同步应用程序通过使用在应用程序和提供程序之间适合的任何机制设置,或者可在两个提供程序之间进行协商。有关协商筛选器的更多信息,请参见筛选同步数据

定义变更单位筛选器时,Sync Framework 在调用源提供程序的 LoadChangeData 时只针对筛选器中包含的变更单位请求数据。

目标提供程序按对待标准变更批的方式接收和应用变更,只是发送到 SaveChangeWithChangeUnits 的数据只包含筛选器中具有的变更单位。

生成要求

示例

本主题中的示例代码演示如何使用元数据存储服务生成一个变更批,该批筛选了包含在变更批中的变更单位。本示例中的副本是一个文本文件,它将联系信息以逗号分隔的值列表形式存储。要同步的项是此文件中包含的联系人。定义筛选器以只包含联系人的姓名和电话号码字段。

设置筛选器

源提供程序实现一个公共方法,该方法允许应用程序设置变更单位筛选器,该筛选器定义在枚举变更时要包含的联系人字段。

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,这样在指定了某一筛选器时,它使用元数据存储服务来生成筛选的变更批。通过创建 ChangeUnitListFilterInfo 对象并使用要包括的变更单位指定列表初始化它来做到这点。将筛选信息传递到 ReplicaMetadata 对象的 GetFilteredChangeBatch 方法。由于元数据存储服务不需要回调提供程序来确定要在筛选器中包括的内容,因此为 filterCallback 参数指定 null

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;
}

后续步骤

接下来,您可能要向您的提供程序添加筛选器协商功能,以便它可与目标提供程序通信以便确定哪一筛选器要用于变更枚举。有关如何协商筛选器的更多信息,请参见如何协商筛选器

请参阅

概念

对常见标准自定义提供程序任务进行编程
筛选同步数据