Freigeben über


Konvertieren von Daten zwischen Anbietern

In vielen Anwendungen synchronisieren alle Anbieter genau die gleiche Art von Daten im gleichen Format. Mehrere Datenbanksynchronisierungsanbieter könnten z. B. Daten für einen Satz von Tabellen in ADO.NET-Datasets synchronisieren und übertragen. In manchen Situationen können sich die Datenformate jedoch unterscheiden. Stellen Sie sich eine Anwendung vor, die Kontakte synchronisiert. Die Anwendung verwendet benutzerdefinierte Anbieter, die von zwei verschiedenen Entwicklern geschrieben wurden. Die für diese Anbieter erforderlichen Daten, unterscheiden sich in zweierlei Hinsicht:

  • Anbieter A überträgt Daten als Bytestream, während Anbieter B Daten als XML-Stream überträgt.

  • Die Daten von Anbieter A bestehen aus drei Feldern: „FirstName“, „LastName“ und „PhoneNumber“. Die Daten von Anbieter B enthalten die Felder „FirstName“ und „LastName“, und „PhoneNumber“ wird unterteilt in „PhoneNumber“ und „AreaCode“.

Um dieses Szenario zu behandeln, können Sie mithilfe von Sync Framework Schnittstellen implementieren, welche die Daten in die für die Anbieter erforderlichen Formate konvertieren. In dieser Situation würden Sie einen Konverter erstellen, der zwei Konvertierungen ausführt. Zunächst wird die Eingabe des Bytestreams in eine XML-Ausgabe konvertiert. Dann wird die XML-Eingabe in eine Bytestreamausgabe konvertiert. Sync Framework erfordert nicht, dass für beide Anbieter Konverter angegeben werden müssen. Der Datenkonvertierungscode, den Sie implementieren, wird von der Synchronisierungssitzung aufgerufen, sodass die Datenkonvertierung während der Änderungsübernahme für den Zielanbieter sichtbar ist.

Stellen Sie sich nun ein Szenario vor, in dem eine Vielzahl von Anbietern Daten unterschiedlicher Formate miteinander synchronisieren müssen. Ein Weg wäre das Erstellen von Konvertern für die einzelnen Anbieterpaare. Dies wäre allerdings kaum zu bewältigen. Eine bessere Alternative ist das Erstellen von Konvertern für jeden Anbieter, welche die Daten in ein Zwischenformat konvertieren. In dieser Situation werden zwei Datenkonvertierungen ausgeführt: vom Quellenanbieter in das Zwischenformat, und vom Zwischenformat in das Format des Zielanbieters.

In der folgenden Tabelle werden die Schnittstellen und Eigenschaften angezeigt, die Sync Framework für die Datenkonvertierung bereitstellt:

Verwalteter Code Nicht verwalteter Code

SyncDataConverter

ISyncDataConverter-Schnittstelle

LocalDataConverter

ISyncDataConversionControl-Schnittstelle

RemoteDataConverter

 

Mit dem folgenden Ansatz können Sie Daten für jeden Anbieter konvertieren:

  1. Implementieren Sie für jeden Anbieter einen Konverter.

    • In verwaltetem Code werden die zwei erforderlichen SyncDataConverter-Methoden implementiert: ConvertDataFromProviderFormat und ConvertDataToProviderFormat.

    • In nicht verwaltetem Code werden die zwei erforderlichen ISyncDataConverter-Methoden implementiert: ConvertDataFromProviderFormat und ConvertDataToProviderFormat.

  2. Legen Sie die Konverter fest, die während der Synchronisierungssitzung verwendet werden sollen.

    • In verwaltetem Code werden die Konverter angegeben, die in den beiden SyncOrchestrator-Eigenschaften implementiert wurden: LocalDataConverter und RemoteDataConverter.

    • In nicht verwaltetem Code werden die Konverter angegeben, die in den beiden ISyncDataConversionControl-Methoden implementiert wurden: SetSourceDataConverter und SetDestinationDataConverter.

In den meisten Fällen implementieren Sie nur zwei der vier verfügbaren Konvertierungsmethoden und legen sie für die Synchronisierungssitzung fest. Die zwei Methoden zur Datenabrufkonvertierung sind nur erforderlich, wenn der von Ihnen verwendete Datenabruf keine Implementierung von IChangeDataRetriever (für verwalteten Code), IAsynchronousDataRetriever oder ISynchronousDataRetriever (für nicht verwalteten Code) ist. In Fällen, in denen Daten in einen Zwischenstatus konvertieret werden, müssen Sie die Implementierung einer Sync Framework-Datenabrufschnittstelle verwenden.

Sync Framework unterstützt Datenkonvertierung für verwaltete Anwendungen, in denen ein oder beide Anbieter nicht verwaltet sind. Beachten Sie, dass der Konvertierungsprozess immer von verwalteten Objekten behandelt wird. Dies kann zu langsameren Synchronisierungszeiten als bei nicht verwalteten Anwendungen führen.

Codebeispiel

Das folgende Codebeispiel veranschaulicht, wie zwei Anbieter synchronisiert werden, die eine Datenkonvertierung erfordern. In der Execute-Methode im Code werden zuerst die zu synchronisierenden Anbieter instanziiert. Anschließend werden zwei Instanzen der Datenkonvertierungsklasse instanziiert, die ein Eingabe- und ein Ausgabeformat akzeptieren. In diesem Beispiel geben die ConvertDataFromProviderFormat-Methode und ConvertDataToProviderFormat-Methode Daten unverändert zurück. In einer realen Anwendung würden Sie jedoch das Eingabeformat in ein geeignetes Ausgabeformat konvertieren.

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

Im folgenden Codebeispiel werden die TryConvertDataRetrieverFromProviderFormat-Methode und TryConvertDataRetrieverToProviderFormat-Methode für die Datenabrufkonvertierung definiert. Beide Methoden akzeptieren einen Datenabruf und eine Liste von Änderungen. Zum Durchführen der Datenabrufkonvertierung wird eine ConvertedDataRetriever-Beispielklasse instanziiert, die von IChangeDataRetriever erbt.

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

Im folgenden Codebeispiel wird die ConvertedDataRetriever-Klasse erstellt, und die LoadChangeData-Methode sowie die IdFormats-Eigenschaft werden definiert. Beim Konvertieren von Datenabrufen muss für die Datenkonvertierung erforderlicher Code in der LoadChangeData-Methode enthalten sein oder von ihr aufgerufen werden.

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

Siehe auch

Konzepte

Integrieren von Daten von verschiedenen Anbietern