Partager via


Conversion de données entre des fournisseurs

Dans de nombreuses applications, tous les fournisseurs synchronisent exactement le même type de données dans le même format. Par exemple, plusieurs fournisseurs de synchronisation de bases de données peuvent synchroniser et transférer des données d'un jeu de tables dans des jeux de données ADO.NET. Cependant, les formats des données peuvent parfois être différents. Prenons l'exemple d'une application qui synchronise des contacts. L'application utilise des fournisseurs personnalisés écrits par deux développeurs. Les données requises par ces fournisseurs diffèrent à deux niveaux :

  • Le fournisseur A transfère les données sous forme de flux d'octets, alors que le fournisseur B les transfère sous forme de flux XML.

  • Les données du fournisseur A comprennent les trois champs suivants : FirstName, LastName et PhoneNumber. Les données du fournisseur B incluent les mêmes champs FirstName et LastName, plus deux champs PhoneNumber et AreaCode à la place du champ PhoneNumber du fournisseur A.

Pour répondre aux besoins de ce scénario, Sync Framework vous permet d'implémenter des interfaces qui convertissent les données au format requis par chaque fournisseur. Ainsi, vous devez écrire un convertisseur qui effectue deux conversions : l'une pour convertir une entrée de flux d'octets en sortie XML, l'autre pour convertir une entrée XML en sortie de flux d'octets. Sync Framework ne requiert pas de spécifier un convertisseur pour chaque fournisseur. Le code de conversion des données que vous implémentez est appelé par la session de synchronisation afin que la conversion des données soit transparente pour le fournisseur de destination pendant le processus d'application des modifications.

Prenons l'exemple d'un autre scénario où un plus grand nombre de fournisseurs doivent synchroniser leurs données de formats différents. Une méthode possible consiste à écrire un convertisseur pour chaque paire de fournisseurs, mais cela peut devenir impossible à gérer. Une meilleure méthode est d'écrire des convertisseurs pour chaque fournisseur qui convertissent les données dans un format intermédiaire. Ainsi, deux conversions de données sont effectuées : l'une du fournisseur de source au format intermédiaire et l'autre, du format intermédiaire au format du fournisseur de destination.

Le tableau suivant répertorie les interfaces et propriétés que Sync Framework fournit pour la conversion de données :

Code managé

Code non managé

SyncDataConverter

Interface ISyncDataConverter

LocalDataConverter

Interface ISyncDataConversionControl

RemoteDataConverter

 

Utilisez la méthode suivante pour convertir les données de chaque fournisseur :

  1. Implémentez un convertisseur pour chaque fournisseur.

  2. Spécifiez les convertisseurs à utiliser pendant la session de synchronisation.

    • Code managé Spécifiez les convertisseurs que vous avez implémentés en utilisant les deux propriétés SyncOrchestrator : LocalDataConverter et RemoteDataConverter.

    • Code non managé Spécifiez les convertisseurs que vous avez implémentés en utilisant les deux méthodes ISyncDataConversionControl : SetSourceDataConverter et SetDestinationDataConverter.

Dans la plupart des cas, vous implémenterez uniquement deux des quatre méthodes de conversion disponibles et vous les spécifierez pour la session de synchronisation. Les deux méthodes de conversion de l'extracteur de données ne sont obligatoires que si l'extracteur de données que vous utilisez n'est pas une implémentation de IChangeDataRetriever (pour le code managé), ou une implémentation de IAsynchronousDataRetriever ou ISynchronousDataRetriever (pour le code non managé). Si vous convertissez les données dans un format intermédiaire, vous devez utiliser une implémentation d'une interface d'extracteur de données de Sync Framework.

Sync Framework prend en charge la conversion des données pour les applications managées dans lesquelles l'un des fournisseurs ou les deux ne sont pas managés. Gardez à l'esprit que le processus de conversion est toujours géré par les objets managés. Par conséquent, la synchronisation peut être moins rapide que pour une application non managée.

Exemple de code

L'exemple de code suivant démontre la façon de synchroniser deux fournisseurs qui nécessitent des conversions de données. Dans la méthode Execute, le code instancie d'abord les fournisseurs qui seront synchronisés, puis instancie ensuite deux instances d'une classe de conversion de données qui accepte un format d'entrée et de sortie. Dans cet exemple, les méthodes ConvertDataFromProviderFormat et ConvertDataToProviderFormat retournent des données non modifiées, mais dans une application réelle, vous convertiriez le format d'entrée en un format de sortie approprié.

public class SampleConversion
{
    public void Execute()
    {

        SyncOrchestrator orchestrator = new SyncOrchestrator();
        orchestrator.Direction = SyncDirectionOrder.Upload;
        orchestrator.LocalProvider = new SampleSyncProvider(localStore);
        orchestrator.RemoteProvider = new SampleSyncProvider(remoteStore);

        DataConverter<DataObject1, DataObject2> localConverter = new DataConverter<DataObject1, DataObject2>();

        DataConverter<DataObject2, DataObject3> remoteConverter = new DataConverter<DataObject2, DataObject3>();

        orchestrator.LocalDataConverter = localConverter;
        orchestrator.RemoteDataConverter = remoteConverter;

        orchestrator.Synchronize();
    }

    string localStore;
    string remoteStore;
}

public class DataConverter<SourceType, DestType> : SyncDataConverter
    where SourceType : IDataObject, new()
    where DestType : IDataObject, new()
{
    public DataConverter()
    {
    }

    public override object ConvertDataFromProviderFormat(LoadChangeContext loadChangeContext, object itemData)
    {
        SourceType dataObj = (SourceType)itemData;

        DestType returnData = new DestType();
        returnData.Data = dataObj.Data;

        return returnData;
    }

    public override object ConvertDataToProviderFormat(LoadChangeContext loadChangeContext, object itemData)
    {
        DestType dataObj = (DestType)itemData;

        SourceType returnData = new SourceType();
        returnData.Data = dataObj.Data;

        return returnData;
    }

    Type sourceType;
    Type destType;
}
Public Class SampleConversion
    Public Sub Execute()

        Dim orchestrator As New SyncOrchestrator()
        orchestrator.Direction = SyncDirectionOrder.Upload
        orchestrator.LocalProvider = New SampleSyncProvider(localStore)
        orchestrator.RemoteProvider = New SampleSyncProvider(remoteStore)

        Dim localConverter As New DataConverter(Of DataObject1, DataObject2)()

        Dim remoteConverter As New DataConverter(Of DataObject2, DataObject3)()

        orchestrator.LocalDataConverter = localConverter
        orchestrator.RemoteDataConverter = remoteConverter

        orchestrator.Synchronize()
    End Sub

    Private localStore As String
    Private remoteStore As String
End Class

Public Class DataConverter(Of SourceType As {IDataObject, New}, DestType As {IDataObject, New})
    Inherits SyncDataConverter
    Public Sub New()
    End Sub

    Public Overloads Overrides Function ConvertDataFromProviderFormat(ByVal loadChangeContext As LoadChangeContext, ByVal itemData As Object) As Object
        Dim dataObj As SourceType = DirectCast(itemData, SourceType)

        Dim returnData As New DestType()
        returnData.Data = dataObj.Data

        Return returnData
    End Function

    Public Overloads Overrides Function ConvertDataToProviderFormat(ByVal loadChangeContext As LoadChangeContext, ByVal itemData As Object) As Object
        Dim dataObj As DestType = DirectCast(itemData, DestType)

        Dim returnData As New SourceType()
        returnData.Data = dataObj.Data

        Return returnData
    End Function

    Private sourceType As Type
    Private destType As Type
End Class

L'exemple de code suivant définit les méthodes de conversion de l'extracteur de données TryConvertDataRetrieverFromProviderFormat et TryConvertDataRetrieverToProviderFormat. Les deux méthodes acceptent un extracteur de données et une liste de modifications. Afin d'exécuter une conversion de l'extracteur de données, elles instancient un exemple de classe ConvertedDataRetriever hérité de IChangeDataRetriever.

public override bool TryConvertDataRetrieverFromProviderFormat(
    object dataRetrieverIn,
    IEnumerable<ItemChange> changes,
    out object dataRetrieverOut)
{
    dataRetrieverOut = new ConvertedDataRetriever<SourceType, DestType>(dataRetrieverIn);
    return true;
}

public override bool TryConvertDataRetrieverToProviderFormat(
    object dataRetrieverIn,
    IEnumerable<ItemChange> changes,
    out object dataRetrieverOut)
{
    dataRetrieverOut = new ConvertedDataRetriever<DestType, SourceType>(dataRetrieverIn);
    return true;
}
Public Overloads Overrides Function TryConvertDataRetrieverFromProviderFormat(ByVal dataRetrieverIn As Object, ByVal changes As IEnumerable(Of ItemChange), ByRef dataRetrieverOut As Object) As Boolean
    dataRetrieverOut = New ConvertedDataRetriever(Of SourceType, DestType)(dataRetrieverIn)
    Return True
End Function

Public Overloads Overrides Function TryConvertDataRetrieverToProviderFormat(ByVal dataRetrieverIn As Object, ByVal changes As IEnumerable(Of ItemChange), ByRef dataRetrieverOut As Object) As Boolean
    dataRetrieverOut = New ConvertedDataRetriever(Of DestType, SourceType)(dataRetrieverIn)
    Return True
End Function

L'exemple de code suivant crée la classe ConvertedDataRetriever et définit la méthode LoadChangeData et la propriété IdFormats. Lors de la conversion des extracteurs de données, tout code requis pour la conversion de données doit être contenu ou appelé par la méthode LoadChangeData.

public class ConvertedDataRetriever<SourceType, DestType> : IChangeDataRetriever
    where SourceType : IDataObject, new()
    where DestType : IDataObject, new()
{
    public ConvertedDataRetriever(object dataRetriever)
    {
        this.dataRetriever = dataRetriever;
    }

    public SyncIdFormatGroup IdFormats
    {
        get
        {
            return ((IChangeDataRetriever)dataRetriever).IdFormats;
        }
    }

    public object LoadChangeData(LoadChangeContext loadChangeContext)
    {
        IChangeDataRetriever iRetriever = (IChangeDataRetriever)dataRetriever;

        object tempData = iRetriever.LoadChangeData(loadChangeContext);

        if (tempData != null)
        {
            return ConvertData(tempData);
        }

        return null;
    }

    private object ConvertData(object itemData)
    {
        SourceType dataObj = (SourceType)itemData;

        DestType returnData = new DestType();
        returnData.Data = dataObj.Data;

        return returnData;
    }

    object dataRetriever;
}
Public Class ConvertedDataRetriever(Of SourceType As {IDataObject, New}, DestType As {IDataObject, New})
    Implements IChangeDataRetriever
    Public Sub New(ByVal dataRetriever As Object)
        Me.dataRetriever = dataRetriever
    End Sub

    Public ReadOnly Property IdFormats() As SyncIdFormatGroup
        Get
            Return DirectCast(dataRetriever, IChangeDataRetriever).IdFormats
        End Get
    End Property

    Public Function LoadChangeData(ByVal loadChangeContext As LoadChangeContext) As Object
        Dim iRetriever As IChangeDataRetriever = DirectCast(dataRetriever, IChangeDataRetriever)

        Dim tempData As Object = iRetriever.LoadChangeData(loadChangeContext)

        If tempData IsNot Nothing Then
            Return ConvertData(tempData)
        End If

        Return Nothing
    End Function

    Private Function ConvertData(ByVal itemData As Object) As Object
        Dim dataObj As SourceType = DirectCast(itemData, SourceType)

        Dim returnData As New DestType()
        returnData.Data = dataObj.Data

        Return returnData
    End Function

    Private dataRetriever As Object
End Class

Voir aussi

Autres ressources

Intégration de données de fournisseurs différents