Share via


N 層同期を構成する方法

このトピックでは、Sync Framework 向けに N 層同期を構成する方法について説明します。このトピックの例では、次に示す Sync Framework の型を中心に説明します。

サンプル コードを実行する方法については、「一般的なクライアントとサーバーの同期タスクのプログラミング」の「操作方法に関するトピックのサンプル アプリケーション」を参照してください。

N 層同期について

N 層同期アーキテクチャでは、次の図に示すように、同期コンポーネントが複数層にまたがって分散されています。

N 層同期トポロジ

2 層アーキテクチャでは、すべてのコンポーネントがクライアント上に存在し、クライアントはサーバーと直接通信します。一方、N 層アーキテクチャでは、サーバー同期プロバイダーがサーバーまたは別の層に存在し、層間の通信は、Windows Communication Foundation (WCF) サービスなどのサービスと ServerSyncProviderProxy オブジェクトによって処理されます。Sync Framework のメリットの 1 つは、2 層アーキテクチャから N 層アーキテクチャに簡単にコードを移行できることです。コードに必要な要素を含め、不要な要素を除外するプロセスが適切に行われている場合、サービスの作成とプロキシの追加が完了した後は、同期エージェント コードを少し変更するだけで済みます。クライアントとサーバーの同期プロバイダーを変更する必要はありません。

次のコード例は、N 層アーキテクチャに関連した主要コンポーネントを示しています。追加の WCF コンポーネントは必須です。Visual Studio 2008 を使用している場合、これらのコンポーネントは自動的に生成されます。詳細については、Visual Studio のマニュアルを参照してください。

API の主要部分

このセクションでは、2 層同期と N 層同期の共通点を表したコード例を示し、N 層同期を構成する際に使用する API の主要部分について述べます。次のコード例では、SyncAgent から派生するクラスを示します。2 層同期では、クライアント プロバイダーとサーバー プロバイダーはローカル プロバイダーおよびリモート プロバイダーとして同期エージェントで直接両方が参照されます。

this.LocalProvider = new SampleClientSyncProvider();

this.RemoteProvider = new SampleServerSyncProvider();
Me.LocalProvider = New SampleClientSyncProvider()

Me.RemoteProvider = New SampleServerSyncProvider()

2 層の例として、クライアント プロバイダーを直接参照するコード例を次に示します。ただし、リモート プロバイダーはサーバー プロバイダーを直接参照する代わりにプロキシを参照します。プロキシは、WCF サービスに参照を渡すことによって作成されます。

this.LocalProvider = new SampleClientSyncProvider();

ServiceReference.ServiceForSyncClient serviceProxy = new ServiceReference.ServiceForSyncClient();
this.RemoteProvider = new ServerSyncProviderProxy(serviceProxy);
Me.LocalProvider = New SampleClientSyncProvider()

Dim serviceProxy As New ServiceReference.ServiceForSyncClient()
Me.RemoteProvider = New ServerSyncProviderProxy(serviceProxy)

次のコード例では、クライアントとサーバーのプロバイダーを作成します。このコードは、2 層と N 層のどちらのアーキテクチャを使用した場合も同一です。

public class SampleClientSyncProvider : SqlCeClientSyncProvider
{

    public SampleClientSyncProvider()
    {
        //Specify a connection string for the sample client database.
        Utility util = new Utility();
        this.ConnectionString = util.ClientConnString;
    }
}
public class SampleServerSyncProvider : DbServerSyncProvider
{
    public SampleServerSyncProvider()
    {
        //Create a connection to the sample server database.
        Utility util = new Utility();
        SqlConnection serverConn = new SqlConnection(util.ServerConnString);
        this.Connection = serverConn;

        //Create a command to retrieve a new anchor value from
        //the server.
        SqlCommand selectNewAnchorCommand = new SqlCommand();
        string newAnchorVariable = "@" + SyncSession.SyncNewReceivedAnchor;
        selectNewAnchorCommand.CommandText = "SELECT " + newAnchorVariable + " = min_active_rowversion() - 1";                                                         
        selectNewAnchorCommand.Parameters.Add(newAnchorVariable, SqlDbType.Timestamp);
        selectNewAnchorCommand.Parameters[newAnchorVariable].Direction = ParameterDirection.Output;
        selectNewAnchorCommand.Connection = serverConn;
        this.SelectNewAnchorCommand = selectNewAnchorCommand;

        //Create a SyncAdapter for the Customer table manually, or
        //by using the SqlSyncAdapterBuilder as in the following
        //code.
        SqlSyncAdapterBuilder customerBuilder = new SqlSyncAdapterBuilder(serverConn);

        customerBuilder.TableName = "Sales.Customer";
        customerBuilder.TombstoneTableName = customerBuilder.TableName + "_Tombstone";
        customerBuilder.SyncDirection = SyncDirection.DownloadOnly;
        customerBuilder.CreationTrackingColumn = "InsertTimestamp";
        customerBuilder.UpdateTrackingColumn = "UpdateTimestamp";
        customerBuilder.DeletionTrackingColumn = "DeleteTimestamp";
        
        SyncAdapter customerSyncAdapter = customerBuilder.ToSyncAdapter();
        customerSyncAdapter.TableName = "Customer";
        this.SyncAdapters.Add(customerSyncAdapter);
    }
}
Public Class SampleClientSyncProvider
    Inherits SqlCeClientSyncProvider

    Public Sub New()
        'Specify a connection string for the sample client database.
        Dim util As New Utility()
        Me.ConnectionString = util.ClientConnString

    End Sub
End Class
Public Class SampleServerSyncProvider
    Inherits DbServerSyncProvider

    Public Sub New()
        'Create a connection to the sample server database.
        Dim util As New Utility()
        Dim serverConn As New SqlConnection(util.ServerConnString)
        Me.Connection = serverConn

        'Create a command to retrieve a new anchor value from
        'the server.
        Dim selectNewAnchorCommand As New SqlCommand()
        Dim newAnchorVariable As String = "@" + SyncSession.SyncNewReceivedAnchor
        selectNewAnchorCommand.CommandText = "SELECT " + newAnchorVariable + " = min_active_rowversion()  1"
        selectNewAnchorCommand.Parameters.Add(newAnchorVariable, SqlDbType.Timestamp)
        selectNewAnchorCommand.Parameters(newAnchorVariable).Direction = ParameterDirection.Output
        selectNewAnchorCommand.Connection = serverConn
        Me.SelectNewAnchorCommand = selectNewAnchorCommand

        'Create a SyncAdapter for the Customer table manually, or
        'by using the SqlSyncAdapterBuilder as in the following
        'code.
        Dim customerBuilder As New SqlSyncAdapterBuilder(serverConn)

        customerBuilder.TableName = "Sales.Customer"
        customerBuilder.TombstoneTableName = customerBuilder.TableName + "_Tombstone"
        customerBuilder.SyncDirection = SyncDirection.DownloadOnly
        customerBuilder.CreationTrackingColumn = "InsertTimestamp"
        customerBuilder.UpdateTrackingColumn = "UpdateTimestamp"
        customerBuilder.DeletionTrackingColumn = "DeleteTimestamp"

        Dim customerSyncAdapter As SyncAdapter = customerBuilder.ToSyncAdapter()
        customerSyncAdapter.TableName = "Customer"
        Me.SyncAdapters.Add(customerSyncAdapter)

    End Sub
End Class

次のコード例では、サービスによって実装されるインターフェイスを作成します。このインターフェイスには、サーバー プロバイダーの 4 つの主要メソッドが用意されています。

[ServiceContract]
public interface IServiceForSync
{
    [OperationContract()]
    SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);

    [OperationContract()]
    SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);

    [OperationContract()]
    SyncSchema GetSchema(Collection<string> tableNames, SyncSession syncSession);

    [OperationContract()]
    SyncServerInfo GetServerInfo(SyncSession syncSession);
}
<ServiceContract()> _
Public Interface IServiceForSync
    <OperationContract()> _
    Function ApplyChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal dataSet As DataSet, ByVal syncSession As SyncSession) As SyncContext

    <OperationContract()> _
    Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext

    <OperationContract()> _
    Function GetSchema(ByVal tableNames As Collection(Of String), ByVal syncSession As SyncSession) As SyncSchema

    <OperationContract()> _
    Function GetServerInfo(ByVal syncSession As SyncSession) As SyncServerInfo
End Interface

次のコード例では、サービスを作成します。このサービスでは、前のコード例で作成したインターフェイスが実装され、サーバー プロバイダーが参照されます。

public class ServiceForSync : IServiceForSync
{

    private SampleServerSyncProvider _serverSyncProvider;

    public ServiceForSync()
    {
         this._serverSyncProvider = new SampleServerSyncProvider();
    }
    
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public virtual SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession) {
        return this._serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession);
    }
    
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public virtual SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession) {
        return this._serverSyncProvider.GetChanges(groupMetadata, syncSession);
    }
    
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public virtual SyncSchema GetSchema(Collection<string> tableNames, SyncSession syncSession) {
        return this._serverSyncProvider.GetSchema(tableNames, syncSession);
    }
    
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
    public virtual SyncServerInfo GetServerInfo(SyncSession syncSession) {
        return this._serverSyncProvider.GetServerInfo(syncSession);
    }       
}
Public Class ServiceForSync
    Implements IServiceForSync

    Private _serverSyncProvider As SampleServerSyncProvider


    Public Sub New()
        Me._serverSyncProvider = New SampleServerSyncProvider()
    End Sub


    <System.Diagnostics.DebuggerNonUserCodeAttribute()> _
    Public Overridable Function ApplyChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal dataSet As DataSet, ByVal syncSession As SyncSession) As SyncContext
        Return Me._serverSyncProvider.ApplyChanges(groupMetadata, dataSet, syncSession)
    End Function


    <System.Diagnostics.DebuggerNonUserCodeAttribute()> _
    Public Overridable Function GetChanges(ByVal groupMetadata As SyncGroupMetadata, ByVal syncSession As SyncSession) As SyncContext
        Return Me._serverSyncProvider.GetChanges(groupMetadata, syncSession)

    End Function


    <System.Diagnostics.DebuggerNonUserCodeAttribute()> _
    Public Overridable Function GetSchema(ByVal tableNames As Collection(Of String), ByVal syncSession As SyncSession) As SyncSchema
        Return Me._serverSyncProvider.GetSchema(tableNames, syncSession)
    End Function


    <System.Diagnostics.DebuggerNonUserCodeAttribute()> _
    Public Overridable Function GetServerInfo(ByVal syncSession As SyncSession) As SyncServerInfo
        Return Me._serverSyncProvider.GetServerInfo(syncSession)
    End Function
End Class

参照

概念

一般的なクライアントとサーバーの同期タスクのプログラミング