伺服器中的資料同步到本地 SQLCE資料庫中的。今天這篇文章演示如何使用同步操作嚮導建立另
外一種方式,即“只同步新更改和增量更改”方式。當前這種方式比之前一種"快照方式"要更加便捷,
而且因為快照方式是採用整表同步,因此不管是資料是否被修改過,都是把所有資料下載到本地,
而今天演示的這種方式是隻同步修改或新新增的資料,可以說是一種經濟實惠的解決方案。
當然,這裡並不是說“快照”方式不好,當資料表中的記錄頻繁變化的話(不穩定)且表中記錄
少時,這種方式也是一種不錯的方案。另外為了“只同步新更改和增量更改”方式,MSF要在遠端數
據伺服器上的相應表格中新增相應的欄位用於記錄資料的修改和新增情況,並且還會新建一個表用
於記錄當前表中的記錄刪除情況(下面會在嚮導介面中有所體現),而這些都會帶來額外的儲存開
銷,所以我個人認為,當資料表中的記錄值變化較小(相對穩定)且表中記錄量大時,這種方案會
是一個不錯的選擇。
好了,開始正文吧。首先要說明的是,如果您看過我的上一篇關於MSF的文章的話,相信您對同步設定嚮導的整個
流程會有個大體上的瞭解。今天的這種“只同步新更改和增量更改”只是在其“配置供離線使用的表”
視窗中進行如下設定(之前流程設定參見上文即可):
下面解釋一下截圖中的一些設定,在伺服器配置一欄,我們看到有幾個下拉選單選項:
“使用下列項比較更新”後面的LastEditDate是我們一會要在遠端伺服器的dnt_posts1表中建立的一個欄位,該欄位是日期型,用於記錄當前資料行的最後一次修改變時間。
“使用下列項比較插入”後而的CreationDate是該行資料的插入時間。
“將已刪除的項移至”後面的dnt_posts_tombstone是當刪除該表中的某一行資料時,將該行資料的主鍵(MSF ADO框架嚮導要求每個表必須有一個主鍵,當前表主題為pid).
"使用下列項比較刪除"後面的DetetionDate是在dnt_posts_tombstone表中的一列(欄位),用於記錄當前dnt_posts1表中的記錄(主鍵)刪除的時間。
“使用下列項比較插入”後而的CreationDate是該行資料的插入時間。
“將已刪除的項移至”後面的dnt_posts_tombstone是當刪除該表中的某一行資料時,將該行資料的主鍵(MSF ADO框架嚮導要求每個表必須有一個主鍵,當前表主題為pid).
"使用下列項比較刪除"後面的DetetionDate是在dnt_posts_tombstone表中的一列(欄位),用於記錄當前dnt_posts1表中的記錄(主鍵)刪除的時間。
通過上面的設定,系統就會擁有了關於進行資料記錄CUD(建立,修改,刪除)的時間戳,據此來
作為進行資料同步時的依據。
當完成了“配置資料同步”視窗中的設定之後。如下圖:
這樣當我們單擊確定時,系統會提示我們如下內容(配置與上一篇文章中SnapShot設定不同):
當我們再次點選確定時,系統開始將本地資料庫(本DEMO為BiDirectSynce#2.sdf)與遠端資料庫
進行同步,如下:
然後接下來的操作與之前的SnapShot方式一樣,也是對要同步的資料表做進一步的設定(使用表中
的哪些欄位等)。然後輸入DataSet名稱並點選“完成”按鈕即完成了嚮導設定工作。
接下來就是在相應的WinForm中顯示同步的資料了,在這裡我偷了個懶,只是將前文中的窗體“複製”
了一份,重新命名為BiDirectForm。當前同步的程式碼與前文也是一樣的。這裡就不多做介紹了。下面繼續
們的內容。
因為設計器完成時給我們生成的程式碼都是從伺服器端向本地同步資料的。而如果本地資料編輯修改
之後,要如何同步(上傳)到遠端伺服器上面呢。其實, MSF在這方面封裝的非常好,我們只要通過下
面的程式碼即可以完成將本地的資料同步到遠端,如下:
//首先是將修改的資料先儲存到本地SDF資料檔案中
SnapDatasView.EndEdit();
//下面更新方法"Update"被過載5次,分別提供了datarow,datarow[],dataset,object[]等型別引數
this.dnt_post1TableAdapter.Update(this.biDirectSynceDataSet.dnt_posts1);
this.dnt_post1TableAdapter.Dispose();
//然後是將本地資料同步到遠端資料伺服器
BiDirectSyncDataSyncAgent SyncAgent = new BiDirectSyncDataSyncAgent();
SyncAgent.dnt_posts1.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
SyncAgent.Synchronize();
SnapDatasView.EndEdit();
//下面更新方法"Update"被過載5次,分別提供了datarow,datarow[],dataset,object[]等型別引數
this.dnt_post1TableAdapter.Update(this.biDirectSynceDataSet.dnt_posts1);
this.dnt_post1TableAdapter.Dispose();
//然後是將本地資料同步到遠端資料伺服器
BiDirectSyncDataSyncAgent SyncAgent = new BiDirectSyncDataSyncAgent();
SyncAgent.dnt_posts1.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
SyncAgent.Synchronize();
上面程式碼中的SyncDirection可謂至關重要,在前文中我曾說過,MSF做資料同步時有四種方式,依
次是(這裡只為加深印象):
Bidirectional:首次同步期間,客戶端通常從伺服器下載架構和一個初始資料集。執行後續同步時,客戶端將更改上載到伺服器,然後從伺服器下載更改(本文演示) 。
DownloadOnly: 首次同步期間,客戶端通常從伺服器下載架構和一個初始資料集。執行後續同步時,客戶端從伺服器下載更改。
Snapshot: 客戶端將從伺服器下載一個資料集。每次同步期間,這些資料都將完全重新整理。
UploadOnly: 首次同步期間,客戶端通常從伺服器下載架構。執行後續同步時,客戶端將更改上載到伺服器。
DownloadOnly: 首次同步期間,客戶端通常從伺服器下載架構和一個初始資料集。執行後續同步時,客戶端從伺服器下載更改。
Snapshot: 客戶端將從伺服器下載一個資料集。每次同步期間,這些資料都將完全重新整理。
UploadOnly: 首次同步期間,客戶端通常從伺服器下載架構。執行後續同步時,客戶端將更改上載到伺服器。
因為MSF設計器預設是Snapshot方式,所以是不支援同步(上傳)遠端的。所以我們這裡使用了
Bidirectional(雙向同步),這樣我們先將本地修改的資料上傳到遠端之後,再將遠端上的資料修改下
載到本地。
整個操作流程是這樣的(首先在本地修改變相應資料):
然後同步到遠端資料伺服器上:
當然如果此時遠端伺服器上有一行記錄(注:與本地修改的記錄不是同一主鍵pid),這條記錄的修
改值也會同步到本地資料檔案(sdf)中。
有經驗的朋友看到這裡會發現一個問題,就是假設如果我在本地修改某一資料行時,此時在遠端數
據庫中有一個使用者也在修改相同的一行資料(同一個主鍵pid)。那當我們進行從本地向遠端的雙向同步
時,最終下載到本地資料檔案中的遠端資料會是那個值呢?
其中這裡MSF的判斷是以優先順序來決定最終使用那一方的資料的。而優先順序毫無一問是遠端資料優
先級要高。所以最終我們在本地修改的資料會被遠端修改的資料所“覆蓋”。MSF預設是這樣的,但如果
我們就是想讓本地的優先順序要大於遠端,換句話說就是想用本地資料“覆蓋”遠端的相同主鍵相同欄位
值的時候,該如何辦呢?
其實這裡有一個很BT的方式,就是手工修改MSF為我們生成的相關應檔案。在本DEMO中,我們修改的
是BiDirectSyncData.Designer.cs檔案中的這一行(line 189)程式碼,原文如下:
this.UpdateCommand.CommandText = @"UPDATE dbo.dnt_posts1 SET [fid] = @fid, [tid] = @tid,
[parentid] = @parentid, [layer] = @layer, [poster] = @poster, [posterid] = @posterid,
[title] = @title, [postdatetime] = @postdatetime, [message] = @message, [ip] = @ip,
[lastedit] = @lastedit, [invisible] = @invisible, [usesig] = @usesig, [htmlon] = @htmlon,
[smileyoff] = @smileyoff, [parseurloff] = @parseurloff, [bbcodeoff] = @bbcodeoff,
[attachment] = @attachment, [rate] = @rate, [ratetimes] = @ratetimes, [LastEditDate] = @LastEditDate,
[CreationDate] = @CreationDate WHERE ([pid] = @pid) AND
(@sync_force_write = 1 OR ([LastEditDate] <= @sync_last_received_anchor))
SET @sync_row_count = @@rowcount";
[parentid] = @parentid, [layer] = @layer, [poster] = @poster, [posterid] = @posterid,
[title] = @title, [postdatetime] = @postdatetime, [message] = @message, [ip] = @ip,
[lastedit] = @lastedit, [invisible] = @invisible, [usesig] = @usesig, [htmlon] = @htmlon,
[smileyoff] = @smileyoff, [parseurloff] = @parseurloff, [bbcodeoff] = @bbcodeoff,
[attachment] = @attachment, [rate] = @rate, [ratetimes] = @ratetimes, [LastEditDate] = @LastEditDate,
[CreationDate] = @CreationDate WHERE ([pid] = @pid) AND
(@sync_force_write = 1 OR ([LastEditDate] <= @sync_last_received_anchor))
SET @sync_row_count = @@rowcount";
大家看到沒有,在上面的SQL語句中有這樣一段內容(倒數第二行):
(@sync_force_write = 1 OR ([LastEditDate] <= @sync_last_received_anchor))
我們只要將@sync_force_write修改為1(讓條件永遠為真),或乾脆將這段內容全部刪除。這樣
就會將我們本地的修改全部提交到遠端資料庫中並最終完成對資料庫中相同資料行的覆蓋。
好了,今天的內容就先到這裡了。在下一篇文章中,我會分析一下設計器嚮導為我們所生成的檔案,
裡面的大部分類都對應著我之前所說的這張圖中的內容,如下:
而為什麼要分析的原因在上面我們已看到了,通過修改這些檔案中的相應內容,會滿足我們開發中
所面對的問題和需求。當然我這裡並不是建議大家去頻繁修改這些檔案,因為這些檔案都是程式碼生成器
“生成的”。如果冒然修改很可能會出現當設計器配置屬性等發生變化時,導致我們的修改被“覆蓋”,這
樣我們修改的程式碼就白寫了。但瞭解這些檔案對於我們瞭解MSF中的Ado.NET支援真的很有幫助,希
望大家理解。
另外下一篇文章也會簡單對比一下SnapShot與本文中所說的“只同步新更改和增量更改”在具體
生成檔案上的一些差異。可以說正是這些差異導致了這兩種方式的不同。
原文連結:http://www.cnblogs.com/daizhj/archive/2008/11/17/1334804.html
作者: daizhj, 代震軍
Tags: 微軟同步框架,ado.net,sqlce
網址: http://daizhj.cnblogs.com/
下載連結,請點選這裡:)