Filtering Data for Simple Providers
In some situations, the destination replica requires only a subset of the data that is available at the source replica. For example, a salesperson might require detailed product information only for those products that she sells regularly. Simple providers enable replicas to filter data by implementing a filtering interface. By filtering data, you can do the following:
Reduce the amount of data sent over the network.
Reduce the amount of storage space that is required on a replica. This is especially important for devices.
Provide custom data partitions based on individual replica requirements.
Avoid or reduce conflicts because different data partitions can be sent to different replicas.
Be aware that simple providers cannot use custom filters or unexpected results may occur. Custom filters are filters that use the CustomFilterInfo class (for managed code) or ICustomFilterInfo interface (for unmanaged code).
To filter data, use the following interfaces:
Managed code: IFilteredSimpleSyncProvider, IRequestFilteredSync, and ISupportFilteredSync
Native code: IFilteredSimpleSyncProvider, IRequestFilteredSync, and ISupportFilteredSync
Managed Code Example
The following code example uses filter negotiation interfaces to determine whether a specific filter should be used during a synchronization session. Filter negotiation enables a destination provider to specify that the source provider should use one or more filters during change enumeration; the source provider can accept or reject a filter. If a source provider does not support any of the requested filters, the destination provider can choose to receive all the data and do the filtering itself. Sync Framework calls the providers appropriately to negotiate filter usage.
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 = ""
The following code example first specifies a filter option of None. This means that items should be filtered out even if they are already known to the destination. The code example then implements the IsItemInFilterScope method, which filters out items based on one of the item field values. After the filter is defined, the code example implements the UseFilterThisSession method. This enables an application to specify whether filtering should be used on a per-session basis.
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
See Also
Concepts
Implementing a Simple Custom Provider
How to: Create a Managed Simple Provider