スポンサーリンク

Sync Frameworkの使い方(SQL Server Compact Edition 3.5編)

SQL Server Compact Edition 3.5のデータベース間でのSync Frameworkを使ったデータ同期方法について説明します。

トランザクションのあまりないようなアプリケーションで、データの多重化をさせたいような場合に有効なソリューションだと思っています。

参照が必要なアセンブリ

Sync Framework 2.1を使用します。以下のPathはx64の場合です。

  • C:\Program Files (x86)\Microsoft SDKs\Microsoft Sync Framework\2.1\Runtime\x86\Microsoft.Synchronization.dll
  • C:\Program Files (x86)\Microsoft SDKs\Microsoft Sync Framework\2.1\Runtime\ADO.NET\V3.1\x86\Microsoft.Synchronization.Data.dll
  • C:\Program Files (x86)\Microsoft SDKs\Microsoft Sync Framework\2.1\Runtime\ADO.NET\V3.1\x86\Microsoft.Synchronization.Data.SqlServerCe.dll

SQL Sever CEで必要な参照アセンブリは以下の通りです。

  • C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Desktop\System.Data.SqlServerCe.dll

基本的にVisual Studioを使う場合には、Visual Studioの参照の追加で出てくるリストにあるはずですが、無ければパスで指定してください。

名前空間

Sync Frameworkの名前空間は以下になります。

  • using Microsoft.Synchronization
  • using Microsoft.Synchronization.Data
  • using Microsoft.Synchronization.Data.SqlServerCe

作業の流れ

作業は以下のような流れになります。

  1. ローカル、リモートそれぞれのデータベースへのConnectionオブジェクトを作る。
  2. ローカル、リモートそれぞれのSyncProviderを作成する。
  3. 新しいスコープ詳細の作成と、データベースに対してそのスコープに対応する同期作業用テーブルの追加を行う
  4. SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。
  5. SyncOrchestratorを作成する。
  6. データの同期を実行する。

Connectionオブジェクトの作成

次のようにsdfファイルへのフルパスをDataSourceに指定してConnectionオブジェクトを作成します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//Connectionオブジェクトを作成する</span>
<span class="hljs-type">string</span> con01 = <span class="hljs-string">"DataSource=<span class="hljs-subst">\"</span>C:<span class="hljs-subst">\\</span>Users<span class="hljs-subst">\\</span>ishisaka<span class="hljs-subst">\\</span>Documents<span class="hljs-subst">\\</span>TestDb1.sdf<span class="hljs-subst">\"</span>"</span>;
SqlCeConnection con1 = new SqlCeConnection(con01);
<span class="hljs-type">string</span> con02 = <span class="hljs-string">"DataSource=<span class="hljs-subst">\"</span>C:<span class="hljs-subst">\\</span>Users<span class="hljs-subst">\\</span>ishisaka<span class="hljs-subst">\\</span>Documents<span class="hljs-subst">\\</span>TestDb2.sdf<span class="hljs-subst">\"</span>"</span>;
SqlCeConnection con2 = new SqlCeConnection(con02);
<span class="hljs-comment">//Connectionオブジェクトを作成する</span> <span class="hljs-type">string</span> con01 = <span class="hljs-string">"DataSource=<span class="hljs-subst">\"</span>C:<span class="hljs-subst">\\</span>Users<span class="hljs-subst">\\</span>ishisaka<span class="hljs-subst">\\</span>Documents<span class="hljs-subst">\\</span>TestDb1.sdf<span class="hljs-subst">\"</span>"</span>; SqlCeConnection con1 = new SqlCeConnection(con01); <span class="hljs-type">string</span> con02 = <span class="hljs-string">"DataSource=<span class="hljs-subst">\"</span>C:<span class="hljs-subst">\\</span>Users<span class="hljs-subst">\\</span>ishisaka<span class="hljs-subst">\\</span>Documents<span class="hljs-subst">\\</span>TestDb2.sdf<span class="hljs-subst">\"</span>"</span>; SqlCeConnection con2 = new SqlCeConnection(con02);
//Connectionオブジェクトを作成する
string con01 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\"";
SqlCeConnection con1 = new SqlCeConnection(con01);
string con02 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\"";
SqlCeConnection con2 = new SqlCeConnection(con02);

SyncProviderの作成

今作ったConnectionオブジェクトを使ったSyncProviderを作成します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-built_in">string</span> scopeName = <span class="hljs-string">"sync_log"</span>;<span class="hljs-comment">//スコープ名の指定</span>
SqlCeSyncProvider provider1 = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncProvider(<span class="hljs-params">scopeName</span>, <span class="hljs-params">con1</span>)</span>;
SqlCeSyncProvider provider2 = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncProvider(<span class="hljs-params">scopeName</span>, <span class="hljs-params">con2</span>)</span>;
<span class="hljs-built_in">string</span> scopeName = <span class="hljs-string">"sync_log"</span>;<span class="hljs-comment">//スコープ名の指定</span> SqlCeSyncProvider provider1 = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncProvider(<span class="hljs-params">scopeName</span>, <span class="hljs-params">con1</span>)</span>; SqlCeSyncProvider provider2 = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncProvider(<span class="hljs-params">scopeName</span>, <span class="hljs-params">con2</span>)</span>;
string scopeName = "sync_log";//スコープ名の指定
SqlCeSyncProvider provider1 = new SqlCeSyncProvider(scopeName, con1);
SqlCeSyncProvider provider2 = new SqlCeSyncProvider(scopeName, con2);

同期のための準備

同期をさせるために新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行います。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span>
<span class="hljs-constructor">CreateSyncScheme(<span class="hljs-params">provider1</span>)</span>;
<span class="hljs-constructor">CreateSyncScheme(<span class="hljs-params">provider2</span>)</span>;
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span> <span class="hljs-constructor">CreateSyncScheme(<span class="hljs-params">provider1</span>)</span>; <span class="hljs-constructor">CreateSyncScheme(<span class="hljs-params">provider2</span>)</span>;
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
CreateSyncScheme(provider1);
CreateSyncScheme(provider2);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span>
<span class="hljs-keyword">private</span> void <span class="hljs-constructor">CreateSyncScheme(SqlCeSyncProvider <span class="hljs-params">provider</span>)</span> {
<span class="hljs-comment">//同期スコープの設定</span>
DbSyncScopeDescription scopeDesc = <span class="hljs-keyword">new</span> <span class="hljs-constructor">DbSyncScopeDescription(<span class="hljs-params">provider</span>.ScopeName)</span>;
<span class="hljs-comment">//ProviderからConnectionオブジェクトの取得</span>
SqlCeConnection ceConn = (SqlCeConnection)provider.Connection;
<span class="hljs-comment">//SqlCeSyncScopeProvisioningの作成</span>
SqlCeSyncScopeProvisioning ceConfig = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncScopeProvisioning(<span class="hljs-params">ceConn</span>)</span>;
<span class="hljs-built_in">string</span> scopeName = provider.ScopeName;
<span class="hljs-comment">//すでに用意されていないのであれば、必要なテーブルを作成する</span>
<span class="hljs-keyword">if</span> (!ceConfig.<span class="hljs-constructor">ScopeExists(<span class="hljs-params">scopeName</span>)</span>) {
scopeDesc.Tables.<span class="hljs-constructor">Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable(<span class="hljs-string">"Log"</span>, <span class="hljs-params">ceConn</span>)</span>);
ceConfig.<span class="hljs-constructor">PopulateFromScopeDescription(<span class="hljs-params">scopeDesc</span>)</span>;
<span class="hljs-comment">//DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する </span>
<span class="hljs-comment">//SQL Server Compact データベースの準備する。</span>
ceConfig.<span class="hljs-constructor">Apply()</span>;
}
}
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span> <span class="hljs-keyword">private</span> void <span class="hljs-constructor">CreateSyncScheme(SqlCeSyncProvider <span class="hljs-params">provider</span>)</span> { <span class="hljs-comment">//同期スコープの設定</span> DbSyncScopeDescription scopeDesc = <span class="hljs-keyword">new</span> <span class="hljs-constructor">DbSyncScopeDescription(<span class="hljs-params">provider</span>.ScopeName)</span>; <span class="hljs-comment">//ProviderからConnectionオブジェクトの取得</span> SqlCeConnection ceConn = (SqlCeConnection)provider.Connection; <span class="hljs-comment">//SqlCeSyncScopeProvisioningの作成</span> SqlCeSyncScopeProvisioning ceConfig = <span class="hljs-keyword">new</span> <span class="hljs-constructor">SqlCeSyncScopeProvisioning(<span class="hljs-params">ceConn</span>)</span>; <span class="hljs-built_in">string</span> scopeName = provider.ScopeName; <span class="hljs-comment">//すでに用意されていないのであれば、必要なテーブルを作成する</span> <span class="hljs-keyword">if</span> (!ceConfig.<span class="hljs-constructor">ScopeExists(<span class="hljs-params">scopeName</span>)</span>) { scopeDesc.Tables.<span class="hljs-constructor">Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable(<span class="hljs-string">"Log"</span>, <span class="hljs-params">ceConn</span>)</span>); ceConfig.<span class="hljs-constructor">PopulateFromScopeDescription(<span class="hljs-params">scopeDesc</span>)</span>; <span class="hljs-comment">//DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する </span> <span class="hljs-comment">//SQL Server Compact データベースの準備する。</span> ceConfig.<span class="hljs-constructor">Apply()</span>; } }
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
private void CreateSyncScheme(SqlCeSyncProvider provider) {
    //同期スコープの設定
    DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription(provider.ScopeName);  
    //ProviderからConnectionオブジェクトの取得
    SqlCeConnection ceConn = (SqlCeConnection)provider.Connection;
    //SqlCeSyncScopeProvisioningの作成
    SqlCeSyncScopeProvisioning ceConfig = new SqlCeSyncScopeProvisioning(ceConn);
    string scopeName = provider.ScopeName;
    //すでに用意されていないのであれば、必要なテーブルを作成する
    if (!ceConfig.ScopeExists(scopeName)) {
        scopeDesc.Tables.Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable("Log", ceConn));
        ceConfig.PopulateFromScopeDescription(scopeDesc);
        //DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する 
        //SQL Server Compact データベースの準備する。
        ceConfig.Apply();
    }
}

Sync Frameworkは同期に必要な情報を保存するため、同期対象となっているデータベースにテーブルをに追加する必要があり、この関数ではその処理を行っています。このテーブルは一度作ればいいので、11行目ですでにそれらのテーブルが存在しているかを確認しています。

RelationalSyncProviderオブジェクトを作成する。

RelationalSyncProviderは同期エージェントに対してデータベース固有の特徴を抽象化して、データベース特定の実装が覆い隠します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。</span>
RelationalSyncProvider srcProvider = provider1;
RelationalSyncProvider destProvider = provider2;
<span class="hljs-comment">//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。</span> RelationalSyncProvider srcProvider = provider1; RelationalSyncProvider destProvider = provider2;
//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。
RelationalSyncProvider srcProvider = provider1;
RelationalSyncProvider destProvider = provider2;

SyncOrchestratorを作成する

SyncOrchestratorを作成し、必要な設定をします。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//SyncOrchestratorを作成する。</span>
SyncOrchestrator orchestrator = <span class="hljs-keyword">new</span> <span class="hljs-type">SyncOrchestrator</span>();
orchestrator.LocalProvider = srcProvider;
orchestrator.RemoteProvider = destProvider;
<span class="hljs-comment">//データの同期方向を設定する。</span>
orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
<span class="hljs-comment">//同期中メッセージ用のイベントを登録する。</span>
orchestrator.SessionProgress += <span class="hljs-keyword">new</span> <span class="hljs-type">EventHandler</span>(orchestrator_SessionProgress);
<span class="hljs-comment">//SyncOrchestratorを作成する。</span> SyncOrchestrator orchestrator = <span class="hljs-keyword">new</span> <span class="hljs-type">SyncOrchestrator</span>(); orchestrator.LocalProvider = srcProvider; orchestrator.RemoteProvider = destProvider; <span class="hljs-comment">//データの同期方向を設定する。</span> orchestrator.Direction = SyncDirectionOrder.UploadAndDownload; <span class="hljs-comment">//同期中メッセージ用のイベントを登録する。</span> orchestrator.SessionProgress += <span class="hljs-keyword">new</span> <span class="hljs-type">EventHandler</span>(orchestrator_SessionProgress);
//SyncOrchestratorを作成する。
SyncOrchestrator orchestrator = new SyncOrchestrator();
orchestrator.LocalProvider = srcProvider;
orchestrator.RemoteProvider = destProvider;
//データの同期方向を設定する。
orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
//同期中メッセージ用のイベントを登録する。
orchestrator.SessionProgress += new EventHandler(orchestrator_SessionProgress);

同期を実行する

同期を実行させます。OrchestratorのSynchronizeメソッドを呼び出すことで同期を実行させ、結果をSyncOperationStatisticsとして返します。コード例にはありませんが、SyncOperationStatisticsには同期実行での統計情報が含まれているので、ユーザーに対して必要な情報表示させたり出来ます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-comment">//データの同期を実行する。</span>
SyncOperationStatistics stats = orchestrator.Synchronize();
<span class="hljs-comment">//データの同期を実行する。</span> SyncOperationStatistics stats = orchestrator.Synchronize();
//データの同期を実行する。
SyncOperationStatistics stats = orchestrator.Synchronize();

全体コード

Log.cs

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Linq;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.Data.SqlServerCe;
<span class="hljs-keyword">using</span> System.Data;
<span class="hljs-keyword">using</span> Microsoft.Synchronization;
<span class="hljs-keyword">using</span> Microsoft.Synchronization.Data;
<span class="hljs-keyword">using</span> Microsoft.Synchronization.Data.SqlServerCe;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">SyncFrameworkDemo</span>
{
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LogData</span>
{
<span class="hljs-keyword">public</span> DateTime Timestamp { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
<span class="hljs-keyword">public</span> String Message { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Log</span>
{
<span class="hljs-comment">//ローカルのデータベースにデータを追加する。</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AddLog</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>)</span> {
<span class="hljs-keyword">string</span> con01 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\""</span>;
<span class="hljs-keyword">using</span> (SqlCeConnection con1 = <span class="hljs-keyword">new</span> SqlCeConnection(con01)) {
con1.Open();
<span class="hljs-keyword">var</span> queryString = <span class="hljs-string">"INSERT INTO Log (timestamp, message) VALUES (@timestamp, @message)"</span>;
<span class="hljs-keyword">using</span> (SqlCeCommand cmd = <span class="hljs-keyword">new</span> SqlCeCommand(queryString, con1)) {
SqlCeParameter timestampPara = <span class="hljs-keyword">new</span> SqlCeParameter(<span class="hljs-string">"@timestamp"</span>, SqlDbType.DateTime);
timestampPara.Value = DateTime.Now;
cmd.Parameters.Add(timestampPara);
SqlCeParameter messeagePara = <span class="hljs-keyword">new</span> SqlCeParameter(<span class="hljs-string">"@message"</span>, SqlDbType.NVarChar, <span class="hljs-number">1000</span>);
messeagePara.Value = message;
cmd.Parameters.Add(messeagePara);
cmd.ExecuteNonQuery();
}
}
}
<span class="hljs-comment">//リモート側のデータベースからデータを取得する。</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> List <span class="hljs-title">GetLogFromRemote</span>(<span class="hljs-params"></span>)</span> {
List logData = <span class="hljs-keyword">new</span> List();
<span class="hljs-keyword">string</span> con02 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\""</span>;
<span class="hljs-keyword">using</span> (SqlCeConnection con2 = <span class="hljs-keyword">new</span> SqlCeConnection(con02)) {
con2.Open();
<span class="hljs-keyword">var</span> queryString = <span class="hljs-string">"SELECT * FROM Log"</span>;
<span class="hljs-keyword">using</span> (SqlCeCommand cmd = <span class="hljs-keyword">new</span> SqlCeCommand(queryString, con2)) {
SqlCeDataReader dr = cmd.ExecuteReader();
<span class="hljs-keyword">while</span> (dr.Read()) {
<span class="hljs-keyword">int</span> timestampOrdinal = dr.GetOrdinal(<span class="hljs-string">"timestamp"</span>);
<span class="hljs-keyword">int</span> messeageOrdinal = dr.GetOrdinal(<span class="hljs-string">"message"</span>);
LogData data = <span class="hljs-keyword">new</span> LogData();
data.Timestamp = dr.GetDateTime(timestampOrdinal);
data.Message = dr.GetString(messeageOrdinal);
logData.Add(data);
}
}
}
<span class="hljs-keyword">return</span> logData;
}
<span class="hljs-comment">//SQL CEのデータベース間でデータを同期する。</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DbSync</span>(<span class="hljs-params"></span>)</span> {
<span class="hljs-comment">//Connectionオブジェクトを作成する</span>
<span class="hljs-keyword">string</span> con01 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\""</span>;
SqlCeConnection con1 = <span class="hljs-keyword">new</span> SqlCeConnection(con01);
<span class="hljs-keyword">string</span> con02 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\""</span>;
SqlCeConnection con2 = <span class="hljs-keyword">new</span> SqlCeConnection(con02);
<span class="hljs-comment">//Providerの作成</span>
<span class="hljs-keyword">string</span> scopeName = <span class="hljs-string">"sync_log"</span>;<span class="hljs-comment">//スコープ名の指定</span>
SqlCeSyncProvider provider1 = <span class="hljs-keyword">new</span> SqlCeSyncProvider(scopeName, con1);
SqlCeSyncProvider provider2 = <span class="hljs-keyword">new</span> SqlCeSyncProvider(scopeName, con2);
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span>
CreateSyncScheme(provider1);
CreateSyncScheme(provider2);
<span class="hljs-comment">//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。</span>
RelationalSyncProvider srcProvider = provider1;
RelationalSyncProvider destProvider = provider2;
<span class="hljs-comment">//SyncOrchestratorを作成する。</span>
SyncOrchestrator orchestrator = <span class="hljs-keyword">new</span> SyncOrchestrator();
orchestrator.LocalProvider = srcProvider;
orchestrator.RemoteProvider = destProvider;
<span class="hljs-comment">//データの同期方向を設定する。</span>
orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
<span class="hljs-comment">//同期中メッセージ用のイベントを登録する。</span>
orchestrator.SessionProgress += <span class="hljs-keyword">new</span> EventHandler(orchestrator_SessionProgress);
<span class="hljs-comment">//データの同期を実行する。</span>
SyncOperationStatistics stats = orchestrator.Synchronize();
srcProvider.Dispose();
destProvider.Dispose();
provider1.Dispose();
provider2.Dispose();
con2.Close();
con1.Close();
}
<span class="hljs-comment">//同期の状態を表示する</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">orchestrator_SessionProgress</span>(<span class="hljs-params"><span class="hljs-keyword">object</span> sender, SyncStagedProgressEventArgs e</span>)</span> {
<span class="hljs-keyword">string</span> providerPosition;
<span class="hljs-keyword">if</span> (e.ReportingProvider == SyncProviderPosition.Local) {
providerPosition = <span class="hljs-string">"ローカル"</span>;
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (e.ReportingProvider == SyncProviderPosition.Remote) {
providerPosition = <span class="hljs-string">"リモート"</span>;
}
<span class="hljs-keyword">else</span> {
providerPosition = <span class="hljs-string">"不明"</span>;
}
<span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeDetection) {
Console.WriteLine(<span class="hljs-string">"{0} 同期元の確認 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>);
}
<span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeEnumeration) {
Console.WriteLine(<span class="hljs-string">"{0} 同期元の変更の抽出 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>);
}
<span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeEnumeration) {
Console.WriteLine(<span class="hljs-string">"{0} 同期先への変更の適用 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>);
}
}
<span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CreateSyncScheme</span>(<span class="hljs-params">SqlCeSyncProvider provider</span>)</span> {
<span class="hljs-comment">//同期スコープの設定</span>
DbSyncScopeDescription scopeDesc = <span class="hljs-keyword">new</span> DbSyncScopeDescription(provider.ScopeName);
<span class="hljs-comment">//ProviderからConnectionオブジェクトの取得</span>
SqlCeConnection ceConn = (SqlCeConnection)provider.Connection;
<span class="hljs-comment">//SqlCeSyncScopeProvisioningの作成</span>
SqlCeSyncScopeProvisioning ceConfig = <span class="hljs-keyword">new</span> SqlCeSyncScopeProvisioning(ceConn);
<span class="hljs-keyword">string</span> scopeName = provider.ScopeName;
<span class="hljs-comment">//すでに用意されていないのであれば、必要なテーブルを作成する</span>
<span class="hljs-keyword">if</span> (!ceConfig.ScopeExists(scopeName)) {
scopeDesc.Tables.Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable(<span class="hljs-string">"Log"</span>, ceConn));
ceConfig.PopulateFromScopeDescription(scopeDesc);
<span class="hljs-comment">//DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する </span>
<span class="hljs-comment">//SQL Server Compact データベースの準備する。</span>
ceConfig.Apply();
}
}
}
}
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">using</span> System.Collections.Generic; <span class="hljs-keyword">using</span> System.Linq; <span class="hljs-keyword">using</span> System.Text; <span class="hljs-keyword">using</span> System.Data.SqlServerCe; <span class="hljs-keyword">using</span> System.Data; <span class="hljs-keyword">using</span> Microsoft.Synchronization; <span class="hljs-keyword">using</span> Microsoft.Synchronization.Data; <span class="hljs-keyword">using</span> Microsoft.Synchronization.Data.SqlServerCe; <span class="hljs-keyword">namespace</span> <span class="hljs-title">SyncFrameworkDemo</span> { <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LogData</span> { <span class="hljs-keyword">public</span> DateTime Timestamp { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } <span class="hljs-keyword">public</span> String Message { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } } <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Log</span> { <span class="hljs-comment">//ローカルのデータベースにデータを追加する。</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">AddLog</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>)</span> { <span class="hljs-keyword">string</span> con01 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\""</span>; <span class="hljs-keyword">using</span> (SqlCeConnection con1 = <span class="hljs-keyword">new</span> SqlCeConnection(con01)) { con1.Open(); <span class="hljs-keyword">var</span> queryString = <span class="hljs-string">"INSERT INTO Log (timestamp, message) VALUES (@timestamp, @message)"</span>; <span class="hljs-keyword">using</span> (SqlCeCommand cmd = <span class="hljs-keyword">new</span> SqlCeCommand(queryString, con1)) { SqlCeParameter timestampPara = <span class="hljs-keyword">new</span> SqlCeParameter(<span class="hljs-string">"@timestamp"</span>, SqlDbType.DateTime); timestampPara.Value = DateTime.Now; cmd.Parameters.Add(timestampPara); SqlCeParameter messeagePara = <span class="hljs-keyword">new</span> SqlCeParameter(<span class="hljs-string">"@message"</span>, SqlDbType.NVarChar, <span class="hljs-number">1000</span>); messeagePara.Value = message; cmd.Parameters.Add(messeagePara); cmd.ExecuteNonQuery(); } } } <span class="hljs-comment">//リモート側のデータベースからデータを取得する。</span> <span class="hljs-function"><span class="hljs-keyword">public</span> List <span class="hljs-title">GetLogFromRemote</span>(<span class="hljs-params"></span>)</span> { List logData = <span class="hljs-keyword">new</span> List(); <span class="hljs-keyword">string</span> con02 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\""</span>; <span class="hljs-keyword">using</span> (SqlCeConnection con2 = <span class="hljs-keyword">new</span> SqlCeConnection(con02)) { con2.Open(); <span class="hljs-keyword">var</span> queryString = <span class="hljs-string">"SELECT * FROM Log"</span>; <span class="hljs-keyword">using</span> (SqlCeCommand cmd = <span class="hljs-keyword">new</span> SqlCeCommand(queryString, con2)) { SqlCeDataReader dr = cmd.ExecuteReader(); <span class="hljs-keyword">while</span> (dr.Read()) { <span class="hljs-keyword">int</span> timestampOrdinal = dr.GetOrdinal(<span class="hljs-string">"timestamp"</span>); <span class="hljs-keyword">int</span> messeageOrdinal = dr.GetOrdinal(<span class="hljs-string">"message"</span>); LogData data = <span class="hljs-keyword">new</span> LogData(); data.Timestamp = dr.GetDateTime(timestampOrdinal); data.Message = dr.GetString(messeageOrdinal); logData.Add(data); } } } <span class="hljs-keyword">return</span> logData; } <span class="hljs-comment">//SQL CEのデータベース間でデータを同期する。</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DbSync</span>(<span class="hljs-params"></span>)</span> { <span class="hljs-comment">//Connectionオブジェクトを作成する</span> <span class="hljs-keyword">string</span> con01 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\""</span>; SqlCeConnection con1 = <span class="hljs-keyword">new</span> SqlCeConnection(con01); <span class="hljs-keyword">string</span> con02 = <span class="hljs-string">"DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\""</span>; SqlCeConnection con2 = <span class="hljs-keyword">new</span> SqlCeConnection(con02); <span class="hljs-comment">//Providerの作成</span> <span class="hljs-keyword">string</span> scopeName = <span class="hljs-string">"sync_log"</span>;<span class="hljs-comment">//スコープ名の指定</span> SqlCeSyncProvider provider1 = <span class="hljs-keyword">new</span> SqlCeSyncProvider(scopeName, con1); SqlCeSyncProvider provider2 = <span class="hljs-keyword">new</span> SqlCeSyncProvider(scopeName, con2); <span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span> CreateSyncScheme(provider1); CreateSyncScheme(provider2); <span class="hljs-comment">//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。</span> RelationalSyncProvider srcProvider = provider1; RelationalSyncProvider destProvider = provider2; <span class="hljs-comment">//SyncOrchestratorを作成する。</span> SyncOrchestrator orchestrator = <span class="hljs-keyword">new</span> SyncOrchestrator(); orchestrator.LocalProvider = srcProvider; orchestrator.RemoteProvider = destProvider; <span class="hljs-comment">//データの同期方向を設定する。</span> orchestrator.Direction = SyncDirectionOrder.UploadAndDownload; <span class="hljs-comment">//同期中メッセージ用のイベントを登録する。</span> orchestrator.SessionProgress += <span class="hljs-keyword">new</span> EventHandler(orchestrator_SessionProgress); <span class="hljs-comment">//データの同期を実行する。</span> SyncOperationStatistics stats = orchestrator.Synchronize(); srcProvider.Dispose(); destProvider.Dispose(); provider1.Dispose(); provider2.Dispose(); con2.Close(); con1.Close(); } <span class="hljs-comment">//同期の状態を表示する</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">orchestrator_SessionProgress</span>(<span class="hljs-params"><span class="hljs-keyword">object</span> sender, SyncStagedProgressEventArgs e</span>)</span> { <span class="hljs-keyword">string</span> providerPosition; <span class="hljs-keyword">if</span> (e.ReportingProvider == SyncProviderPosition.Local) { providerPosition = <span class="hljs-string">"ローカル"</span>; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (e.ReportingProvider == SyncProviderPosition.Remote) { providerPosition = <span class="hljs-string">"リモート"</span>; } <span class="hljs-keyword">else</span> { providerPosition = <span class="hljs-string">"不明"</span>; } <span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeDetection) { Console.WriteLine(<span class="hljs-string">"{0} 同期元の確認 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>); } <span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeEnumeration) { Console.WriteLine(<span class="hljs-string">"{0} 同期元の変更の抽出 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>); } <span class="hljs-keyword">if</span> (e.Stage == SessionProgressStage.ChangeEnumeration) { Console.WriteLine(<span class="hljs-string">"{0} 同期先への変更の適用 {1} %"</span>, providerPosition, e.CompletedWork / e.TotalWork * <span class="hljs-number">100</span>); } } <span class="hljs-comment">//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う</span> <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CreateSyncScheme</span>(<span class="hljs-params">SqlCeSyncProvider provider</span>)</span> { <span class="hljs-comment">//同期スコープの設定</span> DbSyncScopeDescription scopeDesc = <span class="hljs-keyword">new</span> DbSyncScopeDescription(provider.ScopeName); <span class="hljs-comment">//ProviderからConnectionオブジェクトの取得</span> SqlCeConnection ceConn = (SqlCeConnection)provider.Connection; <span class="hljs-comment">//SqlCeSyncScopeProvisioningの作成</span> SqlCeSyncScopeProvisioning ceConfig = <span class="hljs-keyword">new</span> SqlCeSyncScopeProvisioning(ceConn); <span class="hljs-keyword">string</span> scopeName = provider.ScopeName; <span class="hljs-comment">//すでに用意されていないのであれば、必要なテーブルを作成する</span> <span class="hljs-keyword">if</span> (!ceConfig.ScopeExists(scopeName)) { scopeDesc.Tables.Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable(<span class="hljs-string">"Log"</span>, ceConn)); ceConfig.PopulateFromScopeDescription(scopeDesc); <span class="hljs-comment">//DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する </span> <span class="hljs-comment">//SQL Server Compact データベースの準備する。</span> ceConfig.Apply(); } } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlServerCe;
using System.Data;
using Microsoft.Synchronization;
using Microsoft.Synchronization.Data;
using Microsoft.Synchronization.Data.SqlServerCe;
namespace SyncFrameworkDemo
{
    public class LogData
    {
        public DateTime Timestamp { get; set; }
        public String Message { get; set; }
    } 
    public class Log
    {
        //ローカルのデータベースにデータを追加する。
        public void AddLog(string message) {
            string con01 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\"";
            using (SqlCeConnection con1 = new SqlCeConnection(con01)) {
                con1.Open();
                var queryString = "INSERT INTO Log (timestamp, message) VALUES (@timestamp, @message)";
                using (SqlCeCommand cmd = new SqlCeCommand(queryString, con1)) {
                    SqlCeParameter timestampPara = new SqlCeParameter("@timestamp", SqlDbType.DateTime);
                    timestampPara.Value = DateTime.Now;
                    cmd.Parameters.Add(timestampPara);
                    SqlCeParameter messeagePara = new SqlCeParameter("@message", SqlDbType.NVarChar, 1000);
                    messeagePara.Value = message;
                    cmd.Parameters.Add(messeagePara);
                    cmd.ExecuteNonQuery();
                }
            }
        }
       
        //リモート側のデータベースからデータを取得する。
        public List GetLogFromRemote() {
            List logData = new List();
            string con02 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\"";
            using (SqlCeConnection con2 = new SqlCeConnection(con02)) {
                con2.Open();
                var queryString = "SELECT * FROM Log";
                using (SqlCeCommand cmd = new SqlCeCommand(queryString, con2)) {
                    SqlCeDataReader dr = cmd.ExecuteReader();
                    while (dr.Read()) {
                        int timestampOrdinal = dr.GetOrdinal("timestamp");
                        int messeageOrdinal = dr.GetOrdinal("message");
                        LogData data = new LogData();
                        data.Timestamp = dr.GetDateTime(timestampOrdinal);
                        data.Message = dr.GetString(messeageOrdinal);
                        logData.Add(data);
                    }
                }
            }
            return logData;
        }
              
        //SQL CEのデータベース間でデータを同期する。
        public void DbSync() {
            //Connectionオブジェクトを作成する
            string con01 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb1.sdf\"";
            SqlCeConnection con1 = new SqlCeConnection(con01);
            string con02 = "DataSource=\"C:\\Users\\ishisaka\\Documents\\TestDb2.sdf\"";
            SqlCeConnection con2 = new SqlCeConnection(con02);

            //Providerの作成
            string scopeName = "sync_log";//スコープ名の指定
            SqlCeSyncProvider provider1 = new SqlCeSyncProvider(scopeName, con1);
            SqlCeSyncProvider provider2 = new SqlCeSyncProvider(scopeName, con2);
            //新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
            CreateSyncScheme(provider1);
            CreateSyncScheme(provider2);
            //SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。
            RelationalSyncProvider srcProvider = provider1;
            RelationalSyncProvider destProvider = provider2;
            //SyncOrchestratorを作成する。
            SyncOrchestrator orchestrator = new SyncOrchestrator();
            orchestrator.LocalProvider = srcProvider;
            orchestrator.RemoteProvider = destProvider;
            //データの同期方向を設定する。
            orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
            //同期中メッセージ用のイベントを登録する。
            orchestrator.SessionProgress += new EventHandler(orchestrator_SessionProgress);

            //データの同期を実行する。
            SyncOperationStatistics stats = orchestrator.Synchronize();
            srcProvider.Dispose();
            destProvider.Dispose();
            provider1.Dispose();
            provider2.Dispose();
            con2.Close();
            con1.Close();
        }
        
        //同期の状態を表示する
        void orchestrator_SessionProgress(object sender, SyncStagedProgressEventArgs e) {
            string providerPosition;
            if (e.ReportingProvider == SyncProviderPosition.Local) {
                providerPosition = "ローカル";
            }
            else if (e.ReportingProvider == SyncProviderPosition.Remote) {
                providerPosition = "リモート";
            }
            else {
                providerPosition = "不明";
            }
            if (e.Stage == SessionProgressStage.ChangeDetection) {
                Console.WriteLine("{0} 同期元の確認 {1} %", providerPosition, e.CompletedWork / e.TotalWork * 100);
            }
            if (e.Stage == SessionProgressStage.ChangeEnumeration) {
                Console.WriteLine("{0} 同期元の変更の抽出 {1} %", providerPosition, e.CompletedWork / e.TotalWork * 100);
            }
            if (e.Stage == SessionProgressStage.ChangeEnumeration) {
                Console.WriteLine("{0} 同期先への変更の適用 {1} %", providerPosition, e.CompletedWork / e.TotalWork * 100);
            }
        }
        //新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
        private void CreateSyncScheme(SqlCeSyncProvider provider) {
            //同期スコープの設定
            DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription(provider.ScopeName);  
            //ProviderからConnectionオブジェクトの取得
            SqlCeConnection ceConn = (SqlCeConnection)provider.Connection;
            //SqlCeSyncScopeProvisioningの作成
            SqlCeSyncScopeProvisioning ceConfig = new SqlCeSyncScopeProvisioning(ceConn);
            string scopeName = provider.ScopeName;

            //すでに用意されていないのであれば、必要なテーブルを作成する
            if (!ceConfig.ScopeExists(scopeName)) {
                scopeDesc.Tables.Add(SqlCeSyncDescriptionBuilder.GetDescriptionForTable("Log", ceConn));
                ceConfig.PopulateFromScopeDescription(scopeDesc);
                //DbSyncScopeDescription オブジェクトによって表される特定のスコープに対応する 
                //SQL Server Compact データベースの準備する。
                ceConfig.Apply();
            }
        }
    }
}

Program.cs

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Linq;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">namespace</span> SyncFrameworkDemo
{
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{</span>
<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span><span class="hljs-params">(<span class="hljs-built_in">string</span>[] args)</span> </span>{
<span class="hljs-comment">//テスト用クラスのインスタンスを作る</span>
Log <span class="hljs-built_in">log</span> = <span class="hljs-keyword">new</span> Log();
<span class="hljs-comment">//ローカルのデータベースにデータを追加する。</span>
<span class="hljs-built_in">log</span>.AddLog(<span class="hljs-string">"Test"</span>);
<span class="hljs-comment">//同期させる</span>
<span class="hljs-built_in">log</span>.DbSync();
<span class="hljs-comment">//リモートのデータベースが同期したか確認する。</span>
List data = <span class="hljs-built_in">log</span>.GetLogFromRemote();
data.ForEach(d => { Console.WriteLine(<span class="hljs-string">"{0}, {1}"</span>, d.Timestamp, d.Message); });
Console.ReadLine();
}
}
}
<span class="hljs-keyword">using</span> System; <span class="hljs-keyword">using</span> System.Collections.Generic; <span class="hljs-keyword">using</span> System.Linq; <span class="hljs-keyword">using</span> System.Text; <span class="hljs-keyword">namespace</span> SyncFrameworkDemo { <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Program</span> {</span> <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span><span class="hljs-params">(<span class="hljs-built_in">string</span>[] args)</span> </span>{ <span class="hljs-comment">//テスト用クラスのインスタンスを作る</span> Log <span class="hljs-built_in">log</span> = <span class="hljs-keyword">new</span> Log(); <span class="hljs-comment">//ローカルのデータベースにデータを追加する。</span> <span class="hljs-built_in">log</span>.AddLog(<span class="hljs-string">"Test"</span>); <span class="hljs-comment">//同期させる</span> <span class="hljs-built_in">log</span>.DbSync(); <span class="hljs-comment">//リモートのデータベースが同期したか確認する。</span> List data = <span class="hljs-built_in">log</span>.GetLogFromRemote(); data.ForEach(d => { Console.WriteLine(<span class="hljs-string">"{0}, {1}"</span>, d.Timestamp, d.Message); }); Console.ReadLine(); } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SyncFrameworkDemo
{
    class Program
    {
        static void Main(string[] args) {
            //テスト用クラスのインスタンスを作る
            Log log = new Log();
            //ローカルのデータベースにデータを追加する。
            log.AddLog("Test");
            //同期させる
            log.DbSync();
            //リモートのデータベースが同期したか確認する。
            List data = log.GetLogFromRemote();
            data.ForEach(d => { Console.WriteLine("{0}, {1}", d.Timestamp, d.Message); });
            Console.ReadLine();
        }
    }
}

コードダウンロード

Visual Studio 2010のプロジェクトととなっています。

タイトルとURLをコピーしました