スポンサーリンク

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
//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);
//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);
//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
string scopeName = "sync_log";//スコープ名の指定
SqlCeSyncProvider provider1 = new SqlCeSyncProvider(scopeName, con1);
SqlCeSyncProvider provider2 = new SqlCeSyncProvider(scopeName, con2);
string scopeName = "sync_log";//スコープ名の指定 SqlCeSyncProvider provider1 = new SqlCeSyncProvider(scopeName, con1); SqlCeSyncProvider provider2 = new SqlCeSyncProvider(scopeName, con2);
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
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
CreateSyncScheme(provider1);
CreateSyncScheme(provider2);
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う CreateSyncScheme(provider1); CreateSyncScheme(provider2);
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
CreateSyncScheme(provider1);
CreateSyncScheme(provider2);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
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();
}
}
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う 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(); } }
//新しいスコープ詳細の作成とそのスコープに対応するテーブルの追加を行う
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
//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。
RelationalSyncProvider srcProvider = provider1;
RelationalSyncProvider destProvider = provider2;
//SqlCeSyncProviderオブジェクトを利用してRelationalSyncProviderオブジェクトを作成する。 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
//SyncOrchestratorを作成する。
SyncOrchestrator orchestrator = new SyncOrchestrator();
orchestrator.LocalProvider = srcProvider;
orchestrator.RemoteProvider = destProvider;
//データの同期方向を設定する。
orchestrator.Direction = SyncDirectionOrder.UploadAndDownload;
//同期中メッセージ用のイベントを登録する。
orchestrator.SessionProgress += new EventHandler(orchestrator_SessionProgress);
//SyncOrchestratorを作成する。 SyncOrchestrator orchestrator = new SyncOrchestrator(); orchestrator.LocalProvider = srcProvider; orchestrator.RemoteProvider = destProvider; //データの同期方向を設定する。 orchestrator.Direction = SyncDirectionOrder.UploadAndDownload; //同期中メッセージ用のイベントを登録する。 orchestrator.SessionProgress += new EventHandler(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
//データの同期を実行する。
SyncOperationStatistics stats = orchestrator.Synchronize();
//データの同期を実行する。 SyncOperationStatistics stats = orchestrator.Synchronize();
//データの同期を実行する。
SyncOperationStatistics stats = orchestrator.Synchronize();

全体コード

Log.cs

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
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();
}
}
}
}
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(); } } } }
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
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();
}
}
}
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(); } } }
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をコピーしました