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


Фильтрация данных для простых поставщиков

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

  • Уменьшить объем данных, передаваемых по сети.

  • Уменьшить объем, необходимый для хранения данных на реплике. Это особенно важно для устройств.

  • Обеспечить пользовательские секции данных на основе требований конкретной реплики.

  • Избавиться от конфликтов или снизить вероятность их возникновения, поскольку разные секции данных могут отправляться разным репликам.

Учтите, что простые поставщики не могут использовать пользовательские фильтры, в противном случае результаты могут оказаться непредвиденными. Пользовательские фильтры — это фильтры, использующие класс CustomFilterInfo (для управляемого кода) или интерфейс ICustomFilterInfo (для неуправляемого кода).

Для фильтрации данных используются следующие интерфейсы.

Пример управляемого кода

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

public bool RequestFilter
{
    set
    {
        _requestFilter = value; 
    }
}
private bool _requestFilter = false;

void IRequestFilteredSync.SpecifyFilter(FilterRequestCallback filterRequest)
{
    // Request a filter only if this provider represents a filtered replica.
    if (_requestFilter)
    {
        if (!filterRequest("TheFilter", FilteringType.CurrentItemsOnly))
        {
            throw new SyncInvalidOperationException("Could not agree on filter.");
        }
    }
}

bool ISupportFilteredSync.TryAddFilter(object filter, FilteringType filteringType)
{
    if (!((string)filter).Equals("TheFilter"))
    {
        throw new Exception("Filter is incorrect");
    }

    // Remember the filter.
    _filter = (string)filter;

    return true;
}
private string _filter = "";
Public WriteOnly Property RequestFilter() As Boolean
    Set(ByVal value As Boolean)
        _requestFilter = value
    End Set
End Property

Private _requestFilter As Boolean = False

Private Sub SpecifyFilter(ByVal filterRequest As FilterRequestCallback) Implements IRequestFilteredSync.SpecifyFilter
    ' Request a filter only if this provider represents a filtered replica.
    If _requestFilter Then
        If Not filterRequest("TheFilter", FilteringType.CurrentItemsOnly) Then
            Throw New SyncInvalidOperationException("Could not agree on filter.")
        End If
    End If
End Sub

Private Function TryAddFilter(ByVal filter As Object, ByVal filteringType As FilteringType) As Boolean Implements ISupportFilteredSync.TryAddFilter
    If Not DirectCast(filter, String).Equals("TheFilter") Then
        Throw New Exception("Filter is incorrect")
    End If

    ' Remember the filter.
    _filter = DirectCast(filter, String)

    Return True
End Function

Private _filter As String = ""

В следующем примере кода вначале определяется параметр фильтрации None. Это означает, что элементы должны быть отфильтрованы, даже если уже известны в месте назначения. Затем в этом примере кода реализуется метод IsItemInFilterScope, который фильтрует элементы по значению одного из их полей. После определения фильтра в этом примере кода реализуется метод UseFilterThisSession. Это позволяет приложению указать, должна ли осуществляться фильтрация на уровне сеанса.

SimpleSyncProviderFilterOptions IFilteredSimpleSyncProvider.FilterOptions
{
    get
    {
        return SimpleSyncProviderFilterOptions.None;
    }
}

bool IFilteredSimpleSyncProvider.IsItemInFilterScope(ItemFieldDictionary KeyAndVersion)
{
    ulong itemId = (ulong)KeyAndVersion[1].Value;
    ItemData itemData = _store.Get(itemId);
    if (itemData["data"] == "3333")
    {
        return false;
    }

    return true;
}

bool IFilteredSimpleSyncProvider.UseFilterThisSession
{
    get
    {
        // Indicate whether a filter has been requested and agreed upon for this session.
        return ("" != _filter);
    }
}
Private ReadOnly Property FilterOptions() As SimpleSyncProviderFilterOptions Implements IFilteredSimpleSyncProvider.FilterOptions
    Get
        Return SimpleSyncProviderFilterOptions.None
    End Get
End Property

Private Function IsItemInFilterScope(ByVal KeyAndVersion As ItemFieldDictionary) As Boolean Implements IFilteredSimpleSyncProvider.IsItemInFilterScope
    Dim itemId As ULong = KeyAndVersion(1).Value
    Dim data As ItemData = _store.Get(itemId)
    If data("data") Is "3333" Then
        Return False
    End If

    Return True
End Function

Private ReadOnly Property UseFilterThisSession() As Boolean Implements IFilteredSimpleSyncProvider.UseFilterThisSession
    Get
        ' Indicate whether a filter has been requested and agreed upon for this session.
        Return "" Is _filter
    End Get
End Property

См. также

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

Реализация простого пользовательского поставщика
Как создать управляемый простой поставщик