N 層のピア ツー ピアの同期を構成する方法
このトピックでは、Sync Services for ADO.NET 向けに N 層のピア ツー ピアの同期を構成する方法について説明します。このトピックの例では、次に示す Sync Services の型を中心に説明します。
KnowledgeSyncProvider クラスと SyncOrchestrator クラスについては、Microsoft Web サイトにある Sync Framework の主要なドキュメントを参照してください。
N 層同期について
N 層同期アーキテクチャでは、次の図に示すように、同期コンポーネントが複数層にまたがって分散されています。
ローカル ピアは、同期が開始されるピアです。同期を複数のピアから開始する場合は、それぞれのピアに、この図に示すすべてのコンポーネントが含まれている必要があります。ローカル ピアから同期を開始するには、次の手順を実行します。
ローカル ピアでプロバイダをインスタンス化します。このプロバイダは、ローカル ピアのデータベースに直接接続します。
ローカル ピアでプロキシを呼び出します。クライアントとサーバーの同期とは異なり、プロキシが Sync Services API に含まれていないため、KnowledgeSyncProvider から派生するプロキシを作成する必要があります。このプロキシはリモート ピアの Windows Communication Foundation (WCF) などのサービスと通信し、このサービスによりリモート プロバイダがインスタンス化されます。このプロバイダは、リモート ピアのデータベースに直接接続します。
SyncOrchestrator の LocalProvider プロパティと RemoteProvider プロパティに、ローカル プロバイダとリモート プロバイダを指定します。
SyncOrchestrator Synchronize メソッドを呼び出して 2 つのピアを同期します。
例
次のコード例は、N 層アーキテクチャに関連した主要コンポーネントを示しています。追加の WCF コンポーネントは必須です。Visual Studio 2008 を使用している場合、これらのコンポーネントは自動的に生成されます。詳細については、Visual Studio のマニュアルを参照してください。
API の主要部分
このセクションでは、N 層同期の構成時に使用する API の主要部分を示すコード例を示します。次のコード例では、まず、2 つの KnowledgeSyncProvider
オブジェクトをインスタンス化します。ローカル プロバイダは、SetupSyncProvider
メソッドを使用して作成されます。このメソッドは、2 層アプリケーションの他のトピックで使用されるメソッドと同じものです。リモート プロバイダは、SyncProxy
クラスを使用して作成されます。次のコード例にこれを示します。スコープは、各プロバイダに渡されるテーブルの論理的なグループです。プロバイダが作成されると、SyncOrchestrator
オブジェクトがインスタンス化され、同期の方向が設定され、Synchronize
メソッドが呼び出されます。
注意
プロバイダには、DbSyncProvider
ではなく、KnowledgeSyncProvider
オブジェクトが使用されています。これは、SyncProxy
クラスが KnowledgeSyncProvider
から派生するためです。
KnowledgeSyncProvider localProvider;
KnowledgeSyncProvider remoteProvider;
string localConnection = @"Data Source = localhost; Initial Catalog = SyncSamplesDb_Peer1; " +
"Integrated Security = True";
string remoteConnection = @"https://localhost:8000/Sync/SyncService";
string scopeName = "Sales";
SampleSyncProvider sampleSyncProvider = new SampleSyncProvider();
localProvider = sampleSyncProvider.SetupSyncProvider(scopeName, localConnection);
remoteProvider = new SyncProxy(scopeName, remoteConnection);
SyncOrchestrator syncOrchestrator = new SyncOrchestrator();
syncOrchestrator.LocalProvider = localProvider;
syncOrchestrator.RemoteProvider = remoteProvider;
syncOrchestrator.Direction = SyncDirectionOrder.Download;
syncOrchestrator.Synchronize();
Dim localProvider As KnowledgeSyncProvider
Dim remoteProvider As KnowledgeSyncProvider
Dim localConnection As String = "Data Source = localhost; Initial Catalog = SyncSamplesDb_Peer1; " _
& "Integrated Security = True"
Dim remoteConnection As String = "https://localhost:8000/Sync/SyncService"
Dim scopeName As String = "Sales"
Dim sampleSyncProvider As New SampleSyncProvider()
localProvider = sampleSyncProvider.SetupSyncProvider(scopeName, localConnection)
remoteProvider = New SyncProxy(scopeName, remoteConnection)
Dim syncOrchestrator As New SyncOrchestrator()
syncOrchestrator.LocalProvider = localProvider
syncOrchestrator.RemoteProvider = remoteProvider
syncOrchestrator.Direction = SyncDirectionOrder.Download
syncOrchestrator.Synchronize()
次のコード例では、KnowledgeSyncProvider
から派生するプロキシ クラスを作成します。このクラスによって、SyncService
サービスへのチャネルが作成されます。次のコード例にこれを示します。このクラスでは、IdFormats
プロパティを実装しています。DbSyncProvider
で必要なこのプロパティが、KnowledgeSyncProvider
では実装されないためです。SyncProxy
クラスで実装することにより、DbSyncProvider
で実装したのと同じことになります。SyncProxy
クラスには、HTTP 経由で SyncService
サービスのメソッドを呼び出すいくつかのメソッドも含まれます。これらのメソッドは、ローカル ピアとリモート ピアの間で Sync Services によって送信されるデータやメタデータを処理します。ProcessChangeBatch
メソッドで、値をリモート ピアで設定してローカル ピアに戻せるように、参照渡しで remoteSessionStatistics
が渡されます。
public class SyncProxy : KnowledgeSyncProvider
{
public SyncProxy(string scopeName, string url)
{
this.scopeName = scopeName;
WSHttpBinding binding = new WSHttpBinding();
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
binding.OpenTimeout = new TimeSpan(0, 1, 0);
ChannelFactory<ISyncContract> factory = new ChannelFactory<ISyncContract>(binding,
new EndpointAddress(url));
proxy = factory.CreateChannel();
}
//The IdFormat settings for the peer provider.
public override SyncIdFormatGroup IdFormats
{
get
{
if (idFormatGroup == null)
{
idFormatGroup = new SyncIdFormatGroup();
//
// 1 byte change unit ID
//
idFormatGroup.ChangeUnitIdFormat.IsVariableLength = false;
idFormatGroup.ChangeUnitIdFormat.Length = 1;
//
// GUID replica ID
//
idFormatGroup.ReplicaIdFormat.IsVariableLength = false;
idFormatGroup.ReplicaIdFormat.Length = 16;
//
// Global ID for item IDs
//
idFormatGroup.ItemIdFormat.IsVariableLength = true;
idFormatGroup.ItemIdFormat.Length = 10 * 1024;
}
return idFormatGroup;
}
}
public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext)
{
proxy.BeginSession(scopeName);
}
public override void EndSession(SyncSessionContext syncSessionContext)
{
proxy.EndSession();
}
public override void GetSyncBatchParameters(out uint batchSize, out SyncKnowledge knowledge)
{
proxy.GetKnowledge(out batchSize, out knowledge);
}
public override ChangeBatch GetChangeBatch(uint batchSize, SyncKnowledge destinationKnowledge,
out object changeDataRetriever)
{
return proxy.GetChanges(batchSize, destinationKnowledge, out changeDataRetriever);
}
public override void ProcessChangeBatch(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges,
object changeDataRetriever, SyncCallbacks syncCallback, SyncSessionStatistics sessionStatistics)
{
SyncSessionStatistics remoteSessionStatistics = new SyncSessionStatistics();
proxy.ApplyChanges(resolutionPolicy, sourceChanges, changeDataRetriever, ref remoteSessionStatistics);
sessionStatistics.ChangesApplied = remoteSessionStatistics.ChangesApplied;
sessionStatistics.ChangesFailed = remoteSessionStatistics.ChangesFailed;
}
public override FullEnumerationChangeBatch GetFullEnumerationChangeBatch(uint batchSize, SyncId lowerEnumerationBound,
SyncKnowledge knowledgeForDataRetrieval, out object changeDataRetriever)
{
//Do nothing.
//
throw new NotImplementedException();
}
public override void ProcessFullEnumerationChangeBatch(ConflictResolutionPolicy resolutionPolicy,
FullEnumerationChangeBatch sourceChanges, object changeDataRetriever, SyncCallbacks syncCallback,
SyncSessionStatistics sessionStatistics)
{
//Do nothing.
//
throw new NotImplementedException();
}
private string scopeName;
private ISyncContract proxy;
private SyncIdFormatGroup idFormatGroup = null;
}
Public Class SyncProxy
Inherits KnowledgeSyncProvider
Public Sub New(ByVal scopeName As String, ByVal url As String)
Me.scopeName = scopeName
Dim binding As New WSHttpBinding()
binding.ReceiveTimeout = New TimeSpan(0, 10, 0)
binding.OpenTimeout = New TimeSpan(0, 1, 0)
'Dim factory As New ChannelFactory(< ISyncContract > binding, New EndpointAddress(url))
'proxy = factory.CreateChannel()
End Sub 'New
'The IdFormat settings for the peer provider.
Public Overrides ReadOnly Property IdFormats() As SyncIdFormatGroup
Get
If idFormatGroup Is Nothing Then
idFormatGroup = New SyncIdFormatGroup()
'
' 1 byte change unit ID
'
idFormatGroup.ChangeUnitIdFormat.IsVariableLength = False
idFormatGroup.ChangeUnitIdFormat.Length = 1
'
' GUID replica ID
'
idFormatGroup.ReplicaIdFormat.IsVariableLength = False
idFormatGroup.ReplicaIdFormat.Length = 16
'
' Global ID for item IDs
'
idFormatGroup.ItemIdFormat.IsVariableLength = True
idFormatGroup.ItemIdFormat.Length = 10 * 1024
End If
Return idFormatGroup
End Get
End Property
Public Overrides Sub BeginSession(ByVal position As SyncProviderPosition, ByVal syncSessionContext As SyncSessionContext)
proxy.BeginSession(scopeName)
End Sub
Public Overrides Sub EndSession(ByVal syncSessionContext As SyncSessionContext)
proxy.EndSession()
End Sub
Public Overrides Sub GetSyncBatchParameters(ByRef batchSize As System.UInt32, ByRef knowledge As SyncKnowledge) 'ToDo: Unsigned Integers not supported
proxy.GetKnowledge(batchSize, knowledge)
End Sub
Public Overrides Function GetChangeBatch(ByVal batchSize As System.UInt32, ByVal destinationKnowledge As SyncKnowledge, ByRef changeDataRetriever As Object) As ChangeBatch 'ToDo: Unsigned Integers not supported
Return proxy.GetChanges(batchSize, destinationKnowledge, changeDataRetriever)
End Function
Public Overrides Sub ProcessChangeBatch(ByVal resolutionPolicy As ConflictResolutionPolicy, ByVal sourceChanges As ChangeBatch, ByVal changeDataRetriever As Object, ByVal syncCallback As SyncCallbacks, ByVal sessionStatistics As SyncSessionStatistics)
Dim remoteSessionStatistics As New SyncSessionStatistics()
proxy.ApplyChanges(resolutionPolicy, sourceChanges, changeDataRetriever, remoteSessionStatistics)
sessionStatistics.ChangesApplied = remoteSessionStatistics.ChangesApplied
sessionStatistics.ChangesFailed = remoteSessionStatistics.ChangesFailed
End Sub
Public Overrides Function GetFullEnumerationChangeBatch(ByVal batchSize As System.UInt32, ByVal lowerEnumerationBound As SyncId, ByVal knowledgeForDataRetrieval As SyncKnowledge, ByRef changeDataRetriever As Object) As FullEnumerationChangeBatch 'ToDo: Unsigned Integers not supported
'Do nothing.
'
Throw New NotImplementedException()
End Function
Public Overrides Sub ProcessFullEnumerationChangeBatch(ByVal resolutionPolicy As ConflictResolutionPolicy, ByVal sourceChanges As FullEnumerationChangeBatch, ByVal changeDataRetriever As Object, ByVal syncCallback As SyncCallbacks, ByVal sessionStatistics As SyncSessionStatistics)
'Do nothing.
'
Throw New NotImplementedException()
End Sub
Private scopeName As String
Private proxy As ISyncContract
Private idFormatGroup As SyncIdFormatGroup = Nothing
End Class 'SyncProxy
次のコード例では、リモート ピアで、SyncProxy
が通信するサービスを作成します。SyncService
で ISyncContract
を実装しています。次のコード例にこれを示します。BeginSession
メソッドで、このサービスによって DbSyncProvider
が作成されます。その際に呼び出すメソッドはローカル ピアで呼び出したメソッドと同じですが、今回はリモート ピアのサービスから呼び出しています。その他のメソッドは SyncProxy
によって呼び出され、SyncService
によって、BeginSession
で作成された DbSyncProvider
オブジェクトの呼び出しに変換されます。GetFullEnumerationChangeBatch
メソッドと ProcessFullEnumerationChangeBatch
メソッドは、DbSyncprovider
では使用されません。そのため、これらのメソッドは実装されていません。アプリケーションで必要な場合は、これらのメソッドを実装できます。これらのメソッドの詳細については、Sync Framework の主要なドキュメントを参照してください。このドキュメントをダウンロードするには、Microsoft Web サイトにアクセスしてください。
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class SyncService : ISyncContract
{
public void BeginSession(string scopeName)
{
string localConnection = @"Data Source = localhost; Initial Catalog = SyncSamplesDb_Peer2; " +
"Integrated Security = True";
SampleSyncProvider sampleSyncProvider = new SampleSyncProvider();
peerProvider = sampleSyncProvider.SetupSyncProvider(scopeName, localConnection);
}
public void GetKnowledge(
out uint batchSize,
out SyncKnowledge knowledge)
{
peerProvider.GetSyncBatchParameters(out batchSize, out knowledge);
}
public ChangeBatch GetChanges(
uint batchSize,
SyncKnowledge destinationKnowledge,
out object changeData)
{
return peerProvider.GetChangeBatch(batchSize, destinationKnowledge, out changeData);
}
public void ApplyChanges(
ConflictResolutionPolicy resolutionPolicy,
ChangeBatch sourceChanges,
object changeData,
ref SyncSessionStatistics sessionStatistics)
{
SyncCallbacks syncCallback = new SyncCallbacks();
peerProvider.ProcessChangeBatch(resolutionPolicy, sourceChanges, changeData, syncCallback,
sessionStatistics);
}
public void EndSession()
{
peerProvider = null;
}
private DbSyncProvider peerProvider = null;
}
<ServiceBehavior(IncludeExceptionDetailInFaults:=True)> _
Public Class SyncService
Implements ISyncContract
Public Sub BeginSession(ByVal scopeName As String) Implements ISyncContract.BeginSession
Dim localConnection As String = "Data Source = localhost; Initial Catalog = SyncSamplesDb_Peer2; " _
& "Integrated Security = True"
Dim sampleSyncProvider As New SampleSyncProvider()
peerProvider = sampleSyncProvider.SetupSyncProvider(scopeName, localConnection)
End Sub
Public Sub GetKnowledge(ByRef batchSize As System.UInt32, ByRef knowledge As SyncKnowledge) Implements ISyncContract.GetKnowledge
peerProvider.GetSyncBatchParameters(batchSize, knowledge)
End Sub
Public Function GetChanges(ByVal batchSize As System.UInt32, ByVal destinationKnowledge As SyncKnowledge, ByRef changeData As Object) As ChangeBatch Implements ISyncContract.GetChanges
Return peerProvider.GetChangeBatch(batchSize, destinationKnowledge, changeData)
End Function
Public Sub ApplyChanges(ByVal resolutionPolicy As ConflictResolutionPolicy, ByVal sourceChanges As ChangeBatch, ByVal changeData As Object, ByRef sessionStatistics As SyncSessionStatistics) Implements ISyncContract.ApplyChanges
Dim syncCallback As New SyncCallbacks()
peerProvider.ProcessChangeBatch(resolutionPolicy, sourceChanges, changeData, syncCallback, sessionStatistics)
End Sub
Public Sub EndSession() Implements ISyncContract.EndSession
peerProvider = Nothing
End Sub
Private peerProvider As DbSyncProvider = Nothing
End Class
次のコード例では、ISyncContract
インターフェイスを示します。このインターフェイスは、サービス セッションを開始するメソッドや終了するメソッドなど、ピア ツー ピアの同期に必要なメソッドを定義します。ステートレスな同期はサポートされていません。そのため、BeginSession
メソッドと EndSession
メソッドは必須です。
[ServiceContract(SessionMode = SessionMode.Required)]
[ServiceKnownType(typeof(SyncIdFormatGroup))]
[ServiceKnownType(typeof(DbSyncContext))]
public interface ISyncContract
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
void BeginSession(string scopeName);
[OperationContract(IsInitiating = false, IsTerminating = false)]
void GetKnowledge(out uint batchSize, out SyncKnowledge knowledge);
[OperationContract(IsInitiating = false, IsTerminating = false)]
ChangeBatch GetChanges(uint batchSize, SyncKnowledge destinationKnowledge, out object changeData);
[OperationContract(IsInitiating = false, IsTerminating = false)]
void ApplyChanges(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, object changeData,
ref SyncSessionStatistics sessionStatistics);
[OperationContract(IsInitiating = false, IsTerminating = true)]
void EndSession();
}
<ServiceContract(SessionMode:=SessionMode.Required), _
ServiceKnownType(GetType(SyncIdFormatGroup)), _
ServiceKnownType(GetType(DbSyncContext))> _
Public Interface ISyncContract
<OperationContract(IsInitiating:=True, IsTerminating:=False)> _
Sub BeginSession(ByVal scopeName As String)
<OperationContract(IsInitiating:=False, IsTerminating:=False)> _
Sub GetKnowledge(ByRef batchSize As System.UInt32, ByRef knowledge As SyncKnowledge) 'ToDo: Unsigned Integers not supported
<OperationContract(IsInitiating:=False, IsTerminating:=False)> _
Function GetChanges(ByVal batchSize As System.UInt32, ByVal destinationKnowledge As SyncKnowledge, ByRef changeData As Object) As ChangeBatch 'ToDo: Unsigned Integers not supported
<OperationContract(IsInitiating:=False, IsTerminating:=False)> _
Sub ApplyChanges(ByVal resolutionPolicy As ConflictResolutionPolicy, ByVal sourceChanges As ChangeBatch, ByVal changeData As Object, ByRef sessionStatistics As SyncSessionStatistics)
<OperationContract(IsInitiating:=False, IsTerminating:=True)> _
Sub EndSession()
End Interface
次のコード例では、SampleSyncProvider
クラスを示します。このクラスは、2 層および N 層のアプリケーションで使用できます。この SetupSyncProvider
メソッドにより、プロバイダ、および Customers
テーブルのアダプタが作成されます。また、ピア データベースとの間でデータやメタデータを選択して適用するために必要なすべてのコマンドも作成されます。このクラスの詳細については、「変更追跡を構成してピアを同期する方法」を参照してください。
public class SampleSyncProvider
{
public DbSyncProvider SetupSyncProvider(string scopeName, string peerConnString)
{
const int MetadataAgingInHours = 100;
DbSyncProvider peerProvider = new DbSyncProvider();
SqlConnection peerConnection = new SqlConnection(peerConnString);
peerProvider.Connection = peerConnection;
peerProvider.ScopeName = scopeName;
DbSyncAdapter adapterCustomer = new DbSyncAdapter("Customer");
adapterCustomer.RowIdColumns.Add("CustomerId");
SqlCommand chgsCustomerCmd = new SqlCommand();
chgsCustomerCmd.CommandType = CommandType.StoredProcedure;
chgsCustomerCmd.CommandText = "Sales.sp_Customer_SelectChanges";
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMetadataOnly, SqlDbType.Int);
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt);
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncInitialize, SqlDbType.Int);
adapterCustomer.SelectIncrementalChangesCommand = chgsCustomerCmd;
SqlCommand insCustomerCmd = new SqlCommand();
insCustomerCmd.CommandType = CommandType.StoredProcedure;
insCustomerCmd.CommandText = "Sales.sp_Customer_ApplyInsert";
insCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
insCustomerCmd.Parameters.Add("@CustomerName", SqlDbType.NVarChar);
insCustomerCmd.Parameters.Add("@SalesPerson", SqlDbType.NVarChar);
insCustomerCmd.Parameters.Add("@CustomerType", SqlDbType.NVarChar);
insCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
adapterCustomer.InsertCommand = insCustomerCmd;
SqlCommand updCustomerCmd = new SqlCommand();
updCustomerCmd.CommandType = CommandType.StoredProcedure;
updCustomerCmd.CommandText = "Sales.sp_Customer_ApplyUpdate";
updCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
updCustomerCmd.Parameters.Add("@CustomerName", SqlDbType.NVarChar);
updCustomerCmd.Parameters.Add("@SalesPerson", SqlDbType.NVarChar);
updCustomerCmd.Parameters.Add("@CustomerType", SqlDbType.NVarChar);
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt);
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncForceWrite, SqlDbType.Int);
adapterCustomer.UpdateCommand = updCustomerCmd;
SqlCommand delCustomerCmd = new SqlCommand();
delCustomerCmd.CommandType = CommandType.StoredProcedure;
delCustomerCmd.CommandText = "Sales.sp_Customer_ApplyDelete";
delCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
delCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt);
delCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
adapterCustomer.DeleteCommand = delCustomerCmd;
SqlCommand selRowCustomerCmd = new SqlCommand();
selRowCustomerCmd.CommandType = CommandType.StoredProcedure;
selRowCustomerCmd.CommandText = "Sales.sp_Customer_SelectRow";
selRowCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
adapterCustomer.SelectRowCommand = selRowCustomerCmd;
SqlCommand insMetadataCustomerCmd = new SqlCommand();
insMetadataCustomerCmd.CommandType = CommandType.StoredProcedure;
insMetadataCustomerCmd.CommandText = "Sales.sp_Customer_InsertMetadata";
insMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerKey, SqlDbType.Int);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerTimestamp, SqlDbType.BigInt);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerKey, SqlDbType.Int);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerTimestamp, SqlDbType.BigInt);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowIsTombstone, SqlDbType.Int);
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
adapterCustomer.InsertMetadataCommand = insMetadataCustomerCmd;
SqlCommand updMetadataCustomerCmd = new SqlCommand();
updMetadataCustomerCmd.CommandType = CommandType.StoredProcedure;
updMetadataCustomerCmd.CommandText = "Sales.sp_Customer_UpdateMetadata";
updMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerKey, SqlDbType.Int);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerTimestamp, SqlDbType.BigInt);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerKey, SqlDbType.Int);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerTimestamp, SqlDbType.BigInt);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowTimestamp, SqlDbType.BigInt);
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
adapterCustomer.UpdateMetadataCommand = updMetadataCustomerCmd;
SqlCommand delMetadataCustomerCmd = new SqlCommand();
delMetadataCustomerCmd.CommandType = CommandType.StoredProcedure;
delMetadataCustomerCmd.CommandText = "Sales.sp_Customer_DeleteMetadata";
delMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier);
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int);
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowTimestamp, SqlDbType.BigInt);
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
adapterCustomer.DeleteMetadataCommand = delMetadataCustomerCmd;
SqlCommand selMetadataCustomerCmd = new SqlCommand();
selMetadataCustomerCmd.CommandType = CommandType.StoredProcedure;
selMetadataCustomerCmd.CommandText = "Sales.sp_Customer_SelectMetadata";
selMetadataCustomerCmd.Parameters.Add("@metadata_aging_in_hours", SqlDbType.Int).Value = MetadataAgingInHours;
adapterCustomer.SelectMetadataForCleanupCommand = selMetadataCustomerCmd;
peerProvider.SyncAdapters.Add(adapterCustomer);
SqlCommand selectNewTimestampCommand = new SqlCommand();
string newTimestampVariable = "@" + DbSyncSession.SyncNewTimestamp;
selectNewTimestampCommand.CommandText = "SELECT " + newTimestampVariable + " = min_active_rowversion() - 1";
selectNewTimestampCommand.Parameters.Add(newTimestampVariable, SqlDbType.Timestamp);
selectNewTimestampCommand.Parameters[newTimestampVariable].Direction = ParameterDirection.Output;
peerProvider.SelectNewTimestampCommand = selectNewTimestampCommand;
SqlCommand selReplicaInfoCmd = new SqlCommand();
selReplicaInfoCmd.CommandType = CommandType.Text;
selReplicaInfoCmd.CommandText = "SELECT " +
"@" + DbSyncSession.SyncScopeId + " = scope_id, " +
"@" + DbSyncSession.SyncScopeKnowledge + " = scope_sync_knowledge, " +
"@" + DbSyncSession.SyncScopeCleanupKnowledge + " = scope_tombstone_cleanup_knowledge, " +
"@" + DbSyncSession.SyncScopeTimestamp + " = scope_timestamp " +
"FROM Sales.ScopeInfo " +
"WHERE scope_name = @" + DbSyncSession.SyncScopeName;
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeName, SqlDbType.NVarChar, 100);
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeId, SqlDbType.UniqueIdentifier).Direction = ParameterDirection.Output;
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeKnowledge, SqlDbType.VarBinary, 10000).Direction = ParameterDirection.Output;
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeCleanupKnowledge, SqlDbType.VarBinary, 10000).Direction = ParameterDirection.Output;
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeTimestamp, SqlDbType.BigInt).Direction = ParameterDirection.Output;
peerProvider.SelectScopeInfoCommand = selReplicaInfoCmd;
SqlCommand updReplicaInfoCmd = new SqlCommand();
updReplicaInfoCmd.CommandType = CommandType.Text;
updReplicaInfoCmd.CommandText = "UPDATE Sales.ScopeInfo SET " +
"scope_sync_knowledge = @" + DbSyncSession.SyncScopeKnowledge + ", " +
"scope_tombstone_cleanup_knowledge = @" + DbSyncSession.SyncScopeCleanupKnowledge + " " +
"WHERE scope_name = @" + DbSyncSession.SyncScopeName + " AND " +
" ( @" + DbSyncSession.SyncCheckConcurrency + " = 0 or scope_timestamp = @" + DbSyncSession.SyncScopeTimestamp + "); " +
"SET @" + DbSyncSession.SyncRowCount + " = @@rowcount";
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeKnowledge, SqlDbType.VarBinary, 10000);
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeCleanupKnowledge, SqlDbType.VarBinary, 10000);
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeName, SqlDbType.NVarChar, 100);
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int);
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeTimestamp, SqlDbType.BigInt);
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output;
peerProvider.UpdateScopeInfoCommand = updReplicaInfoCmd;
return peerProvider;
}
}
Public Class SampleSyncProvider
Public Function SetupSyncProvider(ByVal scopeName As String, ByVal peerConnString As String) As DbSyncProvider
Const MetadataAgingInHours As Integer = 100
Dim peerProvider As New DbSyncProvider()
Dim peerConnection As New SqlConnection(peerConnString)
peerProvider.Connection = peerConnection
peerProvider.ScopeName = scopeName
Dim adapterCustomer As New DbSyncAdapter("Customer")
adapterCustomer.RowIdColumns.Add("CustomerId")
Dim chgsCustomerCmd As New SqlCommand()
chgsCustomerCmd.CommandType = CommandType.StoredProcedure
chgsCustomerCmd.CommandText = "Sales.sp_Customer_SelectChanges"
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMetadataOnly, SqlDbType.Int)
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt)
chgsCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncInitialize, SqlDbType.Int)
adapterCustomer.SelectIncrementalChangesCommand = chgsCustomerCmd
Dim insCustomerCmd As New SqlCommand()
insCustomerCmd.CommandType = CommandType.StoredProcedure
insCustomerCmd.CommandText = "Sales.sp_Customer_ApplyInsert"
insCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
insCustomerCmd.Parameters.Add("@CustomerName", SqlDbType.NVarChar)
insCustomerCmd.Parameters.Add("@SalesPerson", SqlDbType.NVarChar)
insCustomerCmd.Parameters.Add("@CustomerType", SqlDbType.NVarChar)
insCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
adapterCustomer.InsertCommand = insCustomerCmd
Dim updCustomerCmd As New SqlCommand()
updCustomerCmd.CommandType = CommandType.StoredProcedure
updCustomerCmd.CommandText = "Sales.sp_Customer_ApplyUpdate"
updCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
updCustomerCmd.Parameters.Add("@CustomerName", SqlDbType.NVarChar)
updCustomerCmd.Parameters.Add("@SalesPerson", SqlDbType.NVarChar)
updCustomerCmd.Parameters.Add("@CustomerType", SqlDbType.NVarChar)
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt)
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
updCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncForceWrite, SqlDbType.Int)
adapterCustomer.UpdateCommand = updCustomerCmd
Dim delCustomerCmd As New SqlCommand()
delCustomerCmd.CommandType = CommandType.StoredProcedure
delCustomerCmd.CommandText = "Sales.sp_Customer_ApplyDelete"
delCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
delCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncMinTimestamp, SqlDbType.BigInt)
delCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
adapterCustomer.DeleteCommand = delCustomerCmd
Dim selRowCustomerCmd As New SqlCommand()
selRowCustomerCmd.CommandType = CommandType.StoredProcedure
selRowCustomerCmd.CommandText = "Sales.sp_Customer_SelectRow"
selRowCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
adapterCustomer.SelectRowCommand = selRowCustomerCmd
Dim insMetadataCustomerCmd As New SqlCommand()
insMetadataCustomerCmd.CommandType = CommandType.StoredProcedure
insMetadataCustomerCmd.CommandText = "Sales.sp_Customer_InsertMetadata"
insMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerKey, SqlDbType.Int)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerTimestamp, SqlDbType.BigInt)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerKey, SqlDbType.Int)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerTimestamp, SqlDbType.BigInt)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowIsTombstone, SqlDbType.Int)
insMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
adapterCustomer.InsertMetadataCommand = insMetadataCustomerCmd
Dim updMetadataCustomerCmd As New SqlCommand()
updMetadataCustomerCmd.CommandType = CommandType.StoredProcedure
updMetadataCustomerCmd.CommandText = "Sales.sp_Customer_UpdateMetadata"
updMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerKey, SqlDbType.Int)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCreatePeerTimestamp, SqlDbType.BigInt)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerKey, SqlDbType.Int)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncUpdatePeerTimestamp, SqlDbType.BigInt)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowTimestamp, SqlDbType.BigInt)
updMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
adapterCustomer.UpdateMetadataCommand = updMetadataCustomerCmd
Dim delMetadataCustomerCmd As New SqlCommand()
delMetadataCustomerCmd.CommandType = CommandType.StoredProcedure
delMetadataCustomerCmd.CommandText = "Sales.sp_Customer_DeleteMetadata"
delMetadataCustomerCmd.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier)
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int)
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowTimestamp, SqlDbType.BigInt)
delMetadataCustomerCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
adapterCustomer.DeleteMetadataCommand = delMetadataCustomerCmd
Dim selMetadataCustomerCmd As New SqlCommand()
selMetadataCustomerCmd.CommandType = CommandType.StoredProcedure
selMetadataCustomerCmd.CommandText = "Sales.sp_Customer_SelectMetadata"
selMetadataCustomerCmd.Parameters.Add("@metadata_aging_in_hours", SqlDbType.Int).Value = MetadataAgingInHours
adapterCustomer.SelectMetadataForCleanupCommand = selMetadataCustomerCmd
peerProvider.SyncAdapters.Add(adapterCustomer)
Dim selectNewTimestampCommand As New SqlCommand()
Dim newTimestampVariable As String = "@" + DbSyncSession.SyncNewTimestamp
selectNewTimestampCommand.CommandText = "SELECT " + newTimestampVariable + " = min_active_rowversion() - 1"
selectNewTimestampCommand.Parameters.Add(newTimestampVariable, SqlDbType.Timestamp)
selectNewTimestampCommand.Parameters(newTimestampVariable).Direction = ParameterDirection.Output
peerProvider.SelectNewTimestampCommand = selectNewTimestampCommand
Dim selReplicaInfoCmd As New SqlCommand()
selReplicaInfoCmd.CommandType = CommandType.Text
selReplicaInfoCmd.CommandText = "SELECT " _
& "@" + DbSyncSession.SyncScopeId + " = scope_id, " _
& "@" + DbSyncSession.SyncScopeKnowledge + " = scope_sync_knowledge, " _
& "@" + DbSyncSession.SyncScopeCleanupKnowledge + " = scope_tombstone_cleanup_knowledge, " _
& "@" + DbSyncSession.SyncScopeTimestamp + " = scope_timestamp " _
& "FROM Sales.ScopeInfo " _
& "WHERE scope_name = @" + DbSyncSession.SyncScopeName
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeName, SqlDbType.NVarChar, 100)
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeId, SqlDbType.UniqueIdentifier).Direction = ParameterDirection.Output
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeKnowledge, SqlDbType.VarBinary, 10000).Direction = ParameterDirection.Output
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeCleanupKnowledge, SqlDbType.VarBinary, 10000).Direction = ParameterDirection.Output
selReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeTimestamp, SqlDbType.BigInt).Direction = ParameterDirection.Output
peerProvider.SelectScopeInfoCommand = selReplicaInfoCmd
Dim updReplicaInfoCmd As New SqlCommand()
updReplicaInfoCmd.CommandType = CommandType.Text
updReplicaInfoCmd.CommandText = "UPDATE Sales.ScopeInfo SET " _
& "scope_sync_knowledge = @" + DbSyncSession.SyncScopeKnowledge + ", " _
& "scope_tombstone_cleanup_knowledge = @" + DbSyncSession.SyncScopeCleanupKnowledge + " " _
& "WHERE scope_name = @" + DbSyncSession.SyncScopeName + " AND " _
& " ( @" + DbSyncSession.SyncCheckConcurrency + " = 0 or scope_timestamp = @" + DbSyncSession.SyncScopeTimestamp + "); " _
& "SET @" + DbSyncSession.SyncRowCount + " = @@rowcount"
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeKnowledge, SqlDbType.VarBinary, 10000)
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeCleanupKnowledge, SqlDbType.VarBinary, 10000)
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeName, SqlDbType.NVarChar, 100)
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncCheckConcurrency, SqlDbType.Int)
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncScopeTimestamp, SqlDbType.BigInt)
updReplicaInfoCmd.Parameters.Add("@" + DbSyncSession.SyncRowCount, SqlDbType.Int).Direction = ParameterDirection.Output
peerProvider.UpdateScopeInfoCommand = updReplicaInfoCmd
Return peerProvider
End Function 'SetupSyncProvider
End Class 'SampleSyncProvider