RDA實(shí)現(xiàn)SQL CE與SQL Server間數(shù)據(jù)存取
PPC程序與桌面PC進(jìn)行通信的編程方式目前有兩種,1、利用Socket編程與桌面程序進(jìn)行通信;2、利用RDA和Replication(復(fù)制)進(jìn)行數(shù)據(jù)庫(kù)編程來(lái)完成與桌面SQL Server數(shù)據(jù)庫(kù)的存取。利用Socket編程實(shí)際上就是通過(guò)TCP/IP協(xié)議與桌面PC進(jìn)行通信,它可以很方便的傳輸一般類(lèi)型的數(shù)據(jù),譬如:字符串、整數(shù)以及字節(jié)等,但是如果需要傳輸類(lèi)型化的數(shù)據(jù)則需要程序員自己去封裝,而且若想由智能設(shè)備從桌面數(shù)據(jù)庫(kù)引擎中返回指定數(shù)據(jù)庫(kù)表的數(shù)據(jù),必須編寫(xiě)桌面接口服務(wù)程序來(lái)查詢(xún)數(shù)據(jù)并將結(jié)果通過(guò)Socket返回給智能設(shè)備。那么如何才能在Pocket PC上做到像在桌面PC上一樣存取本地?cái)?shù)據(jù)庫(kù)甚至是遠(yuǎn)程桌面PC的數(shù)據(jù)庫(kù)呢?通過(guò)在智能設(shè)備Pocket PC上運(yùn)行的SQL Server CE 我們便可以輕松存取放置在Pocket PC上的SQL Server CE數(shù)據(jù)庫(kù),還可以通過(guò)SQL Server CE中的RDA或者合并復(fù)制快速實(shí)現(xiàn)從智能設(shè)備上存取遠(yuǎn)程桌面SQL Server2000的數(shù)據(jù)庫(kù)
什么叫RDA
遠(yuǎn)程數(shù)據(jù)訪問(wèn),即Remote Data Access(簡(jiǎn)稱(chēng)為RDA),這項(xiàng)技術(shù)在Windows CE2.11版本時(shí)已經(jīng)存在,在SQL Server 2000 For CE 出現(xiàn)后,它的功能便更加豐富了,通過(guò)使用這項(xiàng)技術(shù)。并利用各種網(wǎng)絡(luò)環(huán)境,用戶(hù)可以將Pocket PC 連接到遠(yuǎn)程SQL Server 2000 數(shù)據(jù)庫(kù)。如果擁護(hù)是第一次進(jìn)行連接,則移動(dòng)設(shè)備會(huì)從SQL Server 2000 上下載需要查詢(xún)的數(shù)據(jù);如果不是第一次查詢(xún),移動(dòng)設(shè)備則會(huì)對(duì)比本地?cái)?shù)據(jù)庫(kù)和遠(yuǎn)程數(shù)據(jù)庫(kù)中的內(nèi)容。并更新遠(yuǎn)程數(shù)據(jù)庫(kù)中的信息。
RDA技術(shù)的數(shù)據(jù)傳遞。
通過(guò)RDA 技術(shù),可以完成以下幾種類(lèi)型的數(shù)據(jù)傳遞:
從服務(wù)器端下載數(shù)據(jù)。當(dāng)移動(dòng)設(shè)備上的本地?cái)?shù)據(jù)庫(kù)無(wú)內(nèi)容時(shí),可以通過(guò)RDA技術(shù)從遠(yuǎn)程SQL Server 2000服務(wù)器下載初始化數(shù)據(jù)到本地SQL Server CE數(shù)據(jù)庫(kù)。例如,應(yīng)用程序利用RDA技術(shù)下載終端擁護(hù)登陸數(shù)據(jù)和產(chǎn)品原始數(shù)據(jù)到本地移動(dòng)數(shù)據(jù)庫(kù)中,從而完成系統(tǒng)的初始化。如果沒(méi)有這個(gè)最初的初始化步驟,系統(tǒng)將無(wú)法登陸。
向服務(wù)器上傳數(shù)據(jù)。移動(dòng)設(shè)備上的應(yīng)用程序在初始化后能夠讓操作員登陸并使用系統(tǒng)。操作員錄入和采集信息(如GPS的信息和條形碼的信息)都將被保存在移動(dòng)數(shù)據(jù)庫(kù)中,此時(shí),有可以利用RDA技術(shù)將本地?cái)?shù)據(jù)上傳到SQL Server 2000服務(wù)器端。值得注意的是,我們?cè)谠O(shè)計(jì)服務(wù)器端數(shù)據(jù)庫(kù)時(shí),在參加同步的表中不能存在自增量字段,否則容易造成上傳數(shù)據(jù)失敗,起原因是不同的移動(dòng)設(shè)備回對(duì)表中的同一個(gè)字段做自增。
更新服務(wù)器端數(shù)據(jù)。有的時(shí)候,在多個(gè)移動(dòng)設(shè)備上的數(shù)據(jù)庫(kù)和服務(wù)器端的數(shù)據(jù)庫(kù)中都可能存在同一條記錄,這時(shí)服務(wù)器的記錄將以最后一次同步移動(dòng)設(shè)備中的記錄為準(zhǔn)。
下達(dá)無(wú)返回的T—SQL命令操作遠(yuǎn)程服務(wù)器(Submit SQL)。在移動(dòng)設(shè)備上的應(yīng)用程序能夠利用T-SQL命令遠(yuǎn)程操作SQL Server 2000數(shù)據(jù)庫(kù)。這項(xiàng)功能非常實(shí)用,我們通常需要在采集數(shù)據(jù)時(shí)記錄當(dāng)前時(shí)間,但是如果存在多個(gè)移動(dòng)設(shè)備時(shí),各個(gè)移動(dòng)設(shè)備的機(jī)器時(shí)間又可能是不統(tǒng)一,對(duì)這種情況的解決方案就是在每次數(shù)據(jù)同步時(shí),利用Submit SQL技術(shù)刷新服務(wù)器時(shí)間,下載這個(gè)時(shí)間并同時(shí)設(shè)定為移動(dòng)設(shè)備的時(shí)間。
SQL Server CE 架構(gòu)圖 如圖 所示。
Pull(拉數(shù)據(jù))
拉數(shù)據(jù)就是Windows CE 從SQL Server 服務(wù)器獲取數(shù)據(jù)的過(guò)程,這里也可以理解從服務(wù)器中下載數(shù)據(jù)。用戶(hù)不必關(guān)心這之間的處理過(guò)程,只需要調(diào)用ISSCERDA接口的pull方法即可。Pull方法的定義如下:
Virtual /* [id] */ HRESULT STSMETHODCALLTYPY Pull(
/* [in] */ BSTR LocalTableName,
/* [in] */ BSTR SQLSelectString,
/* [in] */BSTR OLEDBConnectionString,
/* [defaultvalue][in] */ RDA_TRACKOPTION TrackOption
/* [defaultvalue][in] */BSTR ErrorTableName)=0;
參數(shù) |
說(shuō)明 |
LocalTableName |
將從服務(wù)器獲取數(shù)據(jù)存儲(chǔ)到此表中。如果此表已經(jīng)存在,將會(huì)發(fā)生錯(cuò)誤。 |
SQLSelectString |
表示從服務(wù)器獲取數(shù)據(jù)的SQL表達(dá)式,它將控制從服務(wù)器取得什么數(shù)據(jù)。同時(shí)也支持那些返回結(jié)果集的存儲(chǔ)過(guò)程和視圖。如果是將服務(wù)器中的多個(gè)表的數(shù)據(jù)傳遞到CE中的一個(gè)表,那么應(yīng)將TRACKOPTION的參數(shù)值設(shè)置成為TRAC |
OLEDBConnectionString |
連接到SQL Server服務(wù)器的連接字符串 |
RDA_TRACKOPTION |
表示SQL Serve CE是否跟蹤存儲(chǔ)獲取服務(wù)器數(shù)據(jù)的表(LocalTableName)的變化。它取值是一個(gè)枚舉值,具有如表 所示的四個(gè)取值。 |
ErrorTableName |
表示CE本地錯(cuò)誤表名。在以后調(diào)用Push方法向服務(wù)器提交變化數(shù)據(jù)時(shí)。如果發(fā)生錯(cuò)誤,此錯(cuò)誤表將被創(chuàng)建,并被寫(xiě)入錯(cuò)誤信息。如果調(diào)用Pull方法時(shí),此錯(cuò)誤表已經(jīng)存在,將會(huì)發(fā)生錯(cuò)誤。 |
表 參數(shù)TrackOption的取值
常量 |
值 |
說(shuō)明 |
TRAC |
1 |
對(duì)于接收到數(shù)據(jù)的表,SQL Serve CE將跟蹤所有的變化,主鍵約束將根據(jù)SQLSelectString被執(zhí)行而被創(chuàng)建。此值是默認(rèn)值。 |
TRAC |
0 |
對(duì)于接收到數(shù)據(jù)的表,SQL Serve CE將不跟蹤所有的變化,主鍵約束在本地表中也是不會(huì)被創(chuàng)建 |
TRAC |
2 |
對(duì)于接收到數(shù)據(jù)的表,SQL Serve CE將跟蹤所有的變化,索引和主鍵如果已經(jīng)在SQL Server表中存在,并且字段被指定在SQLSelectString查詢(xún)語(yǔ)句里,那么服務(wù)器表中的索引和主鍵將創(chuàng)建到CE本地表中。 |
TRAC |
3 |
對(duì)于接收到數(shù)據(jù)的表,SQL Serve CE將不跟蹤所有的變化,索引和主鍵如果已經(jīng)在SQL Server表中存在,并且字段被指定在SQLSelectString查詢(xún)語(yǔ)句里,那么服務(wù)器表中的索引和主鍵將創(chuàng)建到CE本地表中。 |
Push(推數(shù)據(jù))
推數(shù)據(jù)和拉數(shù)據(jù)是完全相反的兩個(gè)方法。推數(shù)據(jù)則是將CE本地庫(kù)中的數(shù)據(jù)上傳到服務(wù)器中。Push方法的定義如下:
Virtual /* [id] */ HRESULT STSMETHODCALLTYPY Push(
/* [in] */ BSTR LocalTableName,
/* [in] */BSTR OLEDBConnectionString,
/* [defaultvalue][in] */ RDA_BATCHOPTION BatchOption)=0;
參數(shù) |
說(shuō)明 |
LocalTableName |
表示將向服務(wù)器上傳的變化數(shù)據(jù)的表名 |
OLEDBConnectionString |
為連接到SQL Server服務(wù)器的連接字符串 |
RDA_BATCHOPTION |
表示上傳數(shù)據(jù)的方法。它取值是一個(gè)枚舉值,具有如表 所示的兩個(gè)取值。 |
表 參數(shù)BatchOption的取值
常量 |
值 |
說(shuō)明 |
BATCHINGOFF |
|
上傳的數(shù)據(jù)被一條一條更新到服務(wù)器 |
BATCHINGON |
|
上傳的數(shù)據(jù)被一次性的更新到服務(wù)器 |
Submit(遠(yuǎn)程T-SQL操作)
Submit方法可以執(zhí)行遠(yuǎn)程SQL語(yǔ)句,也就是可以將SQL語(yǔ)句傳遞到服務(wù)器上直接執(zhí)行,其定義如下:
Virtual /* [id] */ HRESULT STSMETHODCALLTYPY Submit(
/* [in] */ BSTR SQLString,,
/* [in] */BSTR OLEDBConnectionString,)=0;
屬性 |
說(shuō)明 |
SQLString |
表示要執(zhí)行的SQL語(yǔ)句 |
OLEDBConnectionString |
為連接到SQL Server服務(wù)器的連接字符串 |
sql server 2000與sql server ce2.0通過(guò)SqlCeRemoteDataAccess實(shí)現(xiàn)數(shù)據(jù)同步
我已經(jīng)安裝過(guò)sql server 2000和sql server ce2.0,接下來(lái)只是給這兩個(gè)安裝補(bǔ)丁,我安裝的補(bǔ)丁是:Microsoft_sql2ksp4chs1.exe和sqlce20sql2ksp4.exe(也就是sql server ce server tools),確保兩個(gè)補(bǔ)丁是一樣的版本,這里兩個(gè)都是sp4的。
(1)安裝Microsoft_sql2ksp4chs1
要先裝這個(gè)Microsoft_sql2ksp4chs1,他是sql server2000的很容易安裝,按照步驟就好了。
(2)安裝sqlce20sql2ksp4.exe
注意:在安裝前,確保IIS服務(wù)已經(jīng)啟動(dòng)
i. 按照提示安裝
ii. 進(jìn)入SQL Server CE Virtual Directory Creation Wizard界面
iii. 給virtual directory 輸入名稱(chēng) “sscepubs”(這個(gè)你可以自己命名)
iv. 選擇“anonymous access”
v. 下一步,不進(jìn)行任何選擇
vi. 安裝完成
(3)修改SQL Server 2000
進(jìn)入SQL Server的企業(yè)管理器,在正在運(yùn)行的Sever中選擇安全性,新建登陸,新增加用戶(hù)IUSER_計(jì)算機(jī)名(Internet來(lái)賓帳號(hào)), 并在數(shù)據(jù)庫(kù)
訪問(wèn)中選中要訪問(wèn)的數(shù)據(jù)庫(kù),增加角色”db_owner”,點(diǎn)擊確定,完成權(quán)限設(shè)置
(4)測(cè)試是否安裝成功
在IE中輸入http://服務(wù)器的IP地址/sscepubs/sscesa20.dll, 如果連接成功且出現(xiàn)“SQL Server CE Agent”
這樣子就好了,可以利用SqlCeRemoteDataAccess這個(gè)來(lái)實(shí)現(xiàn)同步了
pull是從 SQL Server 數(shù)據(jù)庫(kù)中提取數(shù)據(jù)并將其存儲(chǔ)在 SQL Server CE 數(shù)據(jù)庫(kù)的表中
// Connection String to the SQL Server.
string rdaOleDbConnectString = "Provider=sqloledb; Data Source=MySqlServer;Initial Catalog=Northwind; " +
"User Id=username;Password = <password>";
// Initialize RDA Object.
SqlCeRemoteDataAccess rda = null;
try {
//Try the Pull Operation.
rda = new SqlCeRemoteDataAccess();
rda.InternetLogin = "MyLogin";
rda.InternetPassword = "<password>";
rda.InternetUrl = "http://服務(wù)器的IP地址/sscepubs/sscesa20.dll";
rda.LocalConnectionString = @"Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\ssce.sdf";
rda.Pull(
"Employees",
"Select * from Employees",
rdaOleDbConnectString,
RdaTrackOption.TrackingOnWithIndexes ,
"ErrorTable");
}
catch(SqlCeException) {
//Use you own Error Handling Routine.
}
finally {
//Dispose of the RDA Object.
rda.Dispose();
}
push是將 SQL Server CE 數(shù)據(jù)庫(kù)中跟蹤提取表中的更改傳送回 SQL Server 表
string rdaOleDbConnectString = "Provider=sqloledb; Data Source=MySqlServer;Initial Catalog=Northwind; " +
"User Id=username;Password = <password>";
// Initialize RDA Object.
SqlCeRemoteDataAccess rda = null;
try {
//Try the Pull Operation.
rda = new SqlCeRemoteDataAccess();
rda.InternetLogin = "MyLogin";
rda.InternetPassword = "<password>";
rda.InternetUrl = "http://服務(wù)器的IP地址/sscepubs/sscesa20.dll";
rda.LocalConnectionString = @"Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\ssce.sdf";
rda.Push("MyLocalTable",
rdaOleDbConnectString,
RdaBatchOption.BatchingOn);
}
catch(SqlCeException) {
//Use you own Error Handling Routine.
}
finally {
//Dispose of the RDA Object.
rda.Dispose();
}
剛接觸pda開(kāi)發(fā),什么都不懂,一點(diǎn)點(diǎn)地摸索吧,謝謝我的同事!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using System.Net;
using System.IO;
namespace WinAppGrid
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//創(chuàng)建數(shù)據(jù)庫(kù)的表
private Boolean CreateTable()
{
try
{
SqlCeConnection myconn = new SqlCeConnection("DataSource=mysdf.sdf");
SqlCeCommand com = new SqlCeCommand("create table PC (PCNO NVarChar(10) primary key,XH NVarChar(10) NOT NULL,WERKS NVarChar(4) NOT NULL,PC_DATE NVarChar(10))");
myconn.Open();
com.Connection = myconn;
com.ExecuteNonQuery();
myconn.Close();
MessageBox.Show("創(chuàng)建數(shù)據(jù)庫(kù)成功!");
return true;
}
catch (Exception ex)
{
MessageBox.Show("創(chuàng)建數(shù)據(jù)庫(kù)失敗" + ex.ToString().Substring(1, 60));
return false;
}
}
private void button1_Click(object sender, EventArgs e)
{
//創(chuàng)建數(shù)據(jù)庫(kù)
try
{
if ( File.Exists("mysdf.sdf"))
{
MessageBox.Show("數(shù)據(jù)庫(kù)已經(jīng)存在");
}
else
{
SqlCeEngine eng = new SqlCeEngine("DataSource=mysdf.sdf");
eng.CreateDatabase();
eng.Dispose();
MessageBox.Show("創(chuàng)建數(shù)據(jù)庫(kù)成功");
}
Boolean rtu;
rtu = CreateTable();
if (rtu = false)
{
MessageBox.Show("數(shù)據(jù)表已經(jīng)存在!");
}
else
{
MessageBox.Show("創(chuàng)建數(shù)據(jù)表成功!");
}
}
catch(Exception ex)
{
MessageBox.Show("創(chuàng)建數(shù)據(jù)庫(kù)失敗"+ ex.ToString().Substring(1,60));
}
}
}
}
Q1. 怎么判斷用 RDA Pulled 的表是否是被跟蹤的?什么是 RDA 訂閱表?
A1. 系統(tǒng)表 __sysRDASubscriptions 保存了 RDA 訂閱的信息。如果表被拉下來(lái)時(shí) tracking 選項(xiàng)打開(kāi)了(就是 RdaTrackOption.TrackingOn 或 RdaTrackOption.TrackingOnWithIndexes),那么這個(gè)表就是 RDA 訂閱表。系統(tǒng)表將為它增加一條記錄??傊?,如果被拉下來(lái)的表在 __sysRDASubscriptions 表中有相應(yīng)的記錄,那么它就是被跟蹤的。同樣,如果表在被拉下來(lái)時(shí)沒(méi)有打開(kāi) tracking 選項(xiàng),那么這個(gè)表將沒(méi)有任何 RDA 訂閱信息。
Q2. 為什么我會(huì)得到“SSCE_M_RESTRICTEDDDL – 28605 - Internal error: DDL operations are not allowed on system tables. [,,,Table name,,]” 錯(cuò)誤?這個(gè)錯(cuò)誤表示什么含義?
A2. 當(dāng)你用 RDA 拉下一個(gè)表,同時(shí)設(shè)置了 Tracking On 選項(xiàng)(或者當(dāng)一個(gè)表是 RDA 訂閱的),對(duì)該表的 DDL 操作是受到限制的,所以我們通過(guò)從中復(fù)制數(shù)據(jù)的主表來(lái)維護(hù)架構(gòu)的完整性。因此,當(dāng)你嘗試對(duì) RDA 訂閱表執(zhí)行 DDL 操作時(shí),你將會(huì)遇到這個(gè)錯(cuò)誤。
Q3. 如何避免“SSCE_M_TABLEALREADYEXISTS – 28573 - The LocalTableName parameter is already specified. [,,,Table name,,]”錯(cuò)誤?
A3. 當(dāng) RDA 的 Pull 命令參數(shù)中,本地表名稱(chēng)或錯(cuò)誤表名稱(chēng)所對(duì)應(yīng)的表已經(jīng)存在時(shí),就會(huì)拋出這個(gè)錯(cuò)誤。有兩種方法可以避免這個(gè)錯(cuò)誤:1)刪除引起錯(cuò)誤的表 2)改變 RDA Pull 參數(shù)。
Q4. 如何避免“Duplicate value cannot be inserted into a unique index. [Table name = __sysRDASubscriptions, Constraint name = c_LocalTableName]”錯(cuò)誤?
A4. 在正常情況下,這個(gè)錯(cuò)誤是不應(yīng)該發(fā)生的。不過(guò)有個(gè)缺陷可以導(dǎo)致這個(gè)錯(cuò)誤的出現(xiàn)。關(guān)于這個(gè)缺陷在 KB Article 920272 中有詳細(xì)的討論。如果你正在使用 VS2005 SP1,那么你應(yīng)該不會(huì)再遇到這個(gè)錯(cuò)誤了。如果你確實(shí)遇到了這個(gè)錯(cuò)誤,那么把所有訪問(wèn)數(shù)據(jù)庫(kù)的產(chǎn)品程序文件和客戶(hù)應(yīng)用程序放到同一個(gè)目錄下(比較難理解-_-),最好是 \Windows 目錄。
Q5. 如何在執(zhí)行了 RDA Pull 之后改變 IDENTITY 信息?因?yàn)?RDA 不支持標(biāo)識(shí)范圍管理(Identity Range Management)。
A5. 雖然用 RDA 拉下來(lái)的表是受到 DDL 約束的,但是改變默認(rèn)值和標(biāo)識(shí)信息是沒(méi)有受到限制的。你可以使用 ALTER TABLE <Table Name> ALTER COLUMN <Column Name> <int | bigint> IDENTITY(<New Seed>, <New Step>) 語(yǔ)句修改標(biāo)識(shí)信息。
原文:RDA Subscriptions
[名詞解釋]
RDA:RemoteDataAccess,SQL Server CE 的遠(yuǎn)程數(shù)據(jù)訪問(wèn)同步方式。詳細(xì)介紹看《SQL Server 2005 Mobile Edition 3.0 中的復(fù)制和遠(yuǎn)程數(shù)據(jù)訪問(wèn)功能的技術(shù)對(duì)比》
DDL:Data definition language,數(shù)據(jù)定義語(yǔ)言。
用VS.NET 2005開(kāi)發(fā)SQL MOBILE 2005程序,在RDA同步的PULL函數(shù)中的第4個(gè)參數(shù)只要采用TrackingOn和TrackingOnWithIndexes(另兩個(gè)參數(shù)無(wú)問(wèn)題)就一直發(fā)生一個(gè)錯(cuò)誤:
無(wú)法將重復(fù)值插入唯一索引中。[Table name=_sysRDASubscriptions,Constraint name=c_LocalTableName]
_sysRDASubscriptions是SQl Mobile 2005自動(dòng)產(chǎn)生的系統(tǒng)表,而且只有PULL函數(shù)中的第4個(gè)參數(shù)采用TrackingOn和TrackingOnWithIndexes才會(huì)產(chǎn)生,_sysRDASubscriptions表的其中一個(gè)字段“localTableName”是主鍵,Pull后_sysRDASubscriptions表里自動(dòng)生成一條相關(guān)的記錄。我用Query Analyzer刪除PULL的表,但是_sysRDASubscriptions表的相關(guān)記錄卻不會(huì)自動(dòng)刪除(系統(tǒng)表無(wú)法手動(dòng)修改),導(dǎo)致我再次PULL后就提示上面的錯(cuò)誤?。?!
(注:在程序第一次啟動(dòng)后PULL N次都無(wú)任何問(wèn)題,關(guān)閉程序后再一次啟動(dòng)就一直出現(xiàn)上面的錯(cuò)誤,實(shí)在令人費(fèi)解??! ),當(dāng)表存在時(shí)我在PULL之前都有DROP TABLE,而且我在VS.NET 2003開(kāi)發(fā)SQL SERVER 2.0一直沒(méi)問(wèn)題??!
這個(gè)問(wèn)題我在VS2005 BATE2和VS2005正式版都試過(guò)了,同樣的錯(cuò)誤!??!
問(wèn)題已經(jīng)很久了,問(wèn)了很多地方,一直沒(méi)有解決過(guò)?。。。。。。。。。。。。?!
-----------
終于知道了,原來(lái)是一個(gè)微軟的BUG?。?!暈
http://support.microsoft.com/default.aspx?scid=kb%3Bzh-cn%3B920272
SQL:用RDA實(shí)現(xiàn)SQL CE與SQL Server 之間的數(shù)據(jù)同步
一、 概述
PPC程序與桌面PC進(jìn)行通信的編程方式目前有兩種,1、利用Socket編程與桌面程序進(jìn)行通信;2、利用RDA和Replication(復(fù)制)進(jìn)行數(shù)據(jù)庫(kù)編程來(lái)完成與桌面SQL Server數(shù)據(jù)庫(kù)的存取。利用Socket編程實(shí)際上就是通過(guò)TCP/IP協(xié)議與桌面PC進(jìn)行通信,它可以很方便的傳輸一般類(lèi)型的數(shù)據(jù),譬如:字符串、整數(shù)以及字節(jié)等,但是如果需要傳輸類(lèi)型化的數(shù)據(jù)則需要程序員自己去封裝,而且若想由智能設(shè)備從桌面數(shù)據(jù)庫(kù)引擎中返回指定數(shù)據(jù)庫(kù)表的數(shù)據(jù),必須編寫(xiě)桌面接口服務(wù)程序來(lái)查詢(xún)數(shù)據(jù)并將結(jié)果通過(guò)Socket返回給智能設(shè)備。那么如何才能在Pocket PC上做到像在桌面PC上一樣存取本地?cái)?shù)據(jù)庫(kù)甚至是遠(yuǎn)程桌面PC的數(shù)據(jù)庫(kù)呢?通過(guò)在智能設(shè)備Pocket PC上運(yùn)行的SQL Server CE 我們便可以輕松存取放置在Pocket PC上的SQL Server CE數(shù)據(jù)庫(kù),還可以通過(guò)SQL Server CE中的RDA或者合并復(fù)制快速實(shí)現(xiàn)從智能設(shè)備上存取遠(yuǎn)程桌面SQL Server2000的數(shù)據(jù)庫(kù)。
二、技術(shù)要點(diǎn)
SQL Server CE 全名是Microsoft SQL Server 2000 Windows CE Edition,它為移動(dòng)智能設(shè)備和嵌入式設(shè)備提供了一種存取輕量級(jí)數(shù)據(jù)庫(kù)的解決方案。通過(guò)使用Microsoft Visual Studio .NET 或者 Microsoft eMbedded Visual Tools等開(kāi)發(fā)工具,我們可以將SQL Server的企業(yè)數(shù)據(jù)管理能力擴(kuò)展到基于Windows CE的智能平臺(tái)之上。SQL Server CE可以應(yīng)用到三種典型的環(huán)境中:
1、開(kāi)發(fā)環(huán)境,即用于開(kāi)發(fā)基于SQL Server CE程序的桌面PC,該桌面PC必須包括Microsoft Visual Studio .NET或者M(jìn)icrosoft eMbedded Visual Tools 3.0和Pocket PC SDK開(kāi)發(fā)工具;
2、客戶(hù)端環(huán)境,是用于運(yùn)行基于SQL Server CE程序的Pocket PC設(shè)備,當(dāng)設(shè)備沒(méi)有可用的網(wǎng)絡(luò)連接時(shí),可以使用Microsoft ActiveSync來(lái)與服務(wù)器環(huán)境桌面PC進(jìn)行線纜連接;
3、服務(wù)器環(huán)境,是運(yùn)行Microsoft Internet Information 服務(wù)(IIS) 和Microsoft SQL Server實(shí)例的計(jì)算機(jī),可以將IIS和SQL Server部署在同一臺(tái)已算機(jī)上,也可以分別配置到多臺(tái)計(jì)算上。RDA和合并復(fù)制都需要通過(guò)IIS來(lái)與SQL Server進(jìn)行通信。
SQL Server CE 依靠幾個(gè)組件來(lái)與SQL Server進(jìn)行數(shù)據(jù)交換:
1、數(shù)據(jù)庫(kù)引擎用于管理基于Windows CE設(shè)備上的數(shù)據(jù)存儲(chǔ),并且跟蹤數(shù)據(jù)庫(kù)記錄的添加、更新和刪除操作;
2、SQL Server CE Client Agent 是運(yùn)行在Windows CE設(shè)備上的用于連接的組件,包括復(fù)制對(duì)象、RDA對(duì)象和數(shù)據(jù)庫(kù)引擎,使用這些對(duì)象應(yīng)用程序可以控制與SQL Server的連接;
3、SQL Server CE Server Agent 處理來(lái)自SQL Server CE Client Agent的Http請(qǐng)求。當(dāng)SQL Server CE Client Agent通過(guò)Http協(xié)議向SQL Server CE Server Agent發(fā)送請(qǐng)求時(shí),SQL Server CE Server Agent會(huì)與SQL Server進(jìn)行連接并將查詢(xún)的記錄集通過(guò)Http協(xié)議再傳回給SQL Server CE Client Agent,所有數(shù)據(jù)的傳送都要依賴(lài)IIS來(lái)完成。
由上述通信過(guò)程我們知道,SQL Server CE 的遠(yuǎn)程連接和存取需要使用Web傳輸協(xié)議Http 或者Https,SQL Server CE Client Agent必須運(yùn)行在Windows CE設(shè)備上,SQL Server CE Server Agent則運(yùn)行在桌面PC上,而且該計(jì)算機(jī)還必須安裝有IIS以便使用RDA 或合并復(fù)制來(lái)和SQL Server通信。SQL Server CE 支持的網(wǎng)絡(luò)連接有以太網(wǎng)、無(wú)線局域網(wǎng)和無(wú)線廣域網(wǎng)。通過(guò)使用Microsoft ActiveSync,Pocket PC設(shè)備可以使用串口、紅外線或者USB直接與桌面PC上的SQL Server連接,也可以進(jìn)行SQL Server CE與桌面SQL Server 的連接測(cè)試。
Remote Data Access (RDA)對(duì)象是Microsoft SQL Server 2000 Windows CE (SQL Server CE)用于可編程存取遠(yuǎn)程Microsoft SQL Server 2000 或者M(jìn)icrosoft SQL Server version 7.0 數(shù)據(jù)庫(kù)的ActiveX控件,我們可以使用RDA存取遠(yuǎn)程數(shù)據(jù)庫(kù)就像是在桌面PC上操作本地?cái)?shù)據(jù)庫(kù)一樣簡(jiǎn)單。
三、設(shè)計(jì)思路
我們將使用Visual Basic .Net創(chuàng)建“任務(wù)管理程序 For PPC”項(xiàng)目來(lái)展示如何利用RDA來(lái)完成PPC與PC間的數(shù)據(jù)庫(kù)連接和存取。一名客戶(hù)經(jīng)理助理或銷(xiāo)售人員必須知道今天都要完成哪些任務(wù),上級(jí)領(lǐng)導(dǎo)對(duì)自己都有哪些安排等等信息,雖然可以使用Email或者IM程序進(jìn)行接收和查看,但是如果我們只拿Pocket PC設(shè)備能否完成任務(wù)的接收呢?答案當(dāng)然是肯定的。
在Pocket PC上我們創(chuàng)建數(shù)據(jù)庫(kù)客戶(hù)端程序,編寫(xiě)RDA程序需要用到.net壓縮框架中System.Data.SqlServerCe命名空間中的SqlCeRemoteDataAccess類(lèi)。從桌面PC查詢(xún)并獲取記錄集到Pocket PC上我們需要使用rda.pull方法,pull有多種重載版本,我們使用最常用的版本,localTableName 是將要接收提取的 SQL Server 記錄的 SQL Server CE 本地表的名稱(chēng)。sqlSelectString 為任何有效的 Transact-SQL 語(yǔ)句,包括 SELECT 語(yǔ)句和存儲(chǔ)過(guò)程,它們指定從遠(yuǎn)程 SQL Server 數(shù)據(jù)庫(kù)中提取哪些表、列和記錄以存儲(chǔ)在 SQL Server CE 數(shù)據(jù)庫(kù)中。 oledbConnectionString 是連接 SQL Server 數(shù)據(jù)庫(kù)時(shí)使用的 OLE DB 連接字符串。 trackOption 表示 SQL Server CE 是否跟蹤對(duì)提取表所做的更改,以及提取的表上存在的索引是否轉(zhuǎn)到具有主鍵約束的設(shè)備。我們使用的版本為:
…. rda.Pull("itemlist", "Select * from itemlist where emp_id='" + EMPId + "'", RemoteConnString, RdaTrackOption.TrackingOnWithIndexes) …. |
TrackingOnWithIndexes指示 SQL Server CE跟蹤對(duì)所提取表的所有更改。在本地表上同時(shí)創(chuàng)建 SQL Server 表上存在的索引和主鍵約束。
編寫(xiě)PPC數(shù)據(jù)庫(kù)程序所用到的控件和類(lèi)與編寫(xiě)桌面數(shù)據(jù)庫(kù)程序具有相似性,SqlCeConnection對(duì)應(yīng)SqlConnection,SqlCeDataAdapter對(duì)應(yīng)SqlDataAdapter,SqlCeCommand對(duì)應(yīng)SqlCommand等,SqlCeConnection 對(duì)象表示到智能設(shè)備上的數(shù)據(jù)源的一個(gè)連接,需要向ConnectionString傳遞有效的連接字符串,譬如:
LocalConnString = "Data Source=\Program File\Task\RDA.sdf" |
Sdf文件是SQL Server CE 數(shù)據(jù)庫(kù)文件。 SQL Server CE 只支持一次一個(gè)連接,但是多個(gè)命令可以共享同一連接。在SqlCeConnection連接打開(kāi)的情況下,可以創(chuàng)建SqlCeCommand對(duì)象,并設(shè)置用于執(zhí)行或返回記錄集的SQL語(yǔ)句的Commandtext屬性,SqlCeCommand 調(diào)用的 SQL 語(yǔ)句不支持傳遞參數(shù)的命名參數(shù),必須使用問(wèn)號(hào) (?) 占位符,也可以自定義組成SQL語(yǔ)句的字符串,例如:
…… Dim conn As New SqlCeConnection conn.ConnectionString = LocalConnString Dim selectCMD As SqlCeCommand = New SqlCeCommand selectCMD.CommandText = "update itemlist set finished=1 where id=" + id conn.Open() selectCMD.ExecuteNonQuery() …… |
應(yīng)用程序可以使用rda.push方法將 SQL Server CE 跟蹤提取表中的更改傳送回原始 SQL Server 表。localTableName 是指已經(jīng)從 SQL Server 提取的記錄的 SQL Server CE 本地表的名稱(chēng)。oledbConnectionString 為連接 SQL Server 數(shù)據(jù)庫(kù)時(shí)使用的 OLE DB 連接字符串。batchOption 表示正發(fā)送回 SQL Server 表的更改是組成一批共用同一事務(wù),還是分別應(yīng)用。我們的版本需要將所有行組成一批,歸并到一個(gè)事務(wù)推入SQL Server。
rda.Push("itemlist", RemoteConnString, RdaBatchOption.BatchingOn) |
四、 環(huán)境配置及程序?qū)崿F(xiàn)
很多網(wǎng)友不能成功運(yùn)行SQL Server CE 的RDA和合并復(fù)制程序很大程度都是因?yàn)榕渲脝?wèn)題。正確安裝SQL CE和配置IIS及SQL Server 2000是運(yùn)行SQL CE數(shù)據(jù)庫(kù)程序的關(guān)鍵。安裝SQL Server CE時(shí)需要注意,安裝程序在安裝服務(wù)器工具時(shí)會(huì)抱錯(cuò),這是SQL Server CE本身與SQL Server 2000存在兼容性及安全性問(wèn)題,解決的辦法是先忽略,然后更新桌面SQL Server 2000數(shù)據(jù)庫(kù)引擎到SP3或SP4,根據(jù)所做的更新版本還需要運(yùn)行相應(yīng)的更新程序SQL Server CE 2.0 SP3 For SQL Server 2000 SP3或者SQL Server CE 2.0 SP4 For SQL Server 2000 SP4,這樣SQL Server CE的服務(wù)器組件就可以順利地安裝到了計(jì)算機(jī)中,然后運(yùn)行其附帶的Configure Connectivity Support in IIS創(chuàng)建IIS虛擬目錄sqlce,其指向的實(shí)際本地路徑為:C:\Program Files\Microsoft SQL Server CE 2.0\Server\,可以更改該文件夾路徑為其它,但該文件夾下必須放置著SQL Server CE Server Agent的相關(guān)文件,比如:sscesa20.dll。下一步需要配置存取該虛擬目錄的用戶(hù)、權(quán)限及身份驗(yàn)證方式,我們可以選擇匿名訪問(wèn),并接受IIS的默認(rèn)來(lái)賓用戶(hù),一般以IUSR開(kāi)頭,在存取權(quán)限中需要選中讀取和目錄瀏覽兩項(xiàng),見(jiàn)下圖。
![]() |
配置就緒后,我們可以檢測(cè)SQL Server CE Server Agent工作是否正常,啟動(dòng)IE,在地址欄中輸入 Http://localhost/sqlce/sscesa20.dll,或者將localhost改為實(shí)際的主機(jī)名稱(chēng),瀏覽器返回“SQL Server CE Server Agent”說(shuō)明SQL Server CE Server Agent運(yùn)行正常,IIS配置正確。
![]() ![]() ![]() |
接下來(lái)需要配置SQL Server 2000,我們需要在桌面SQL Server 2000中創(chuàng)建名為T(mén)ask數(shù)據(jù)庫(kù),包含Employee員工表和ItemList任務(wù)表,為ItemList表中ID字段創(chuàng)建主鍵和索引,并且添加在IIS中設(shè)置的可以訪問(wèn)sqlce虛擬目錄和其下文件的IIS來(lái)賓用戶(hù),這樣該用戶(hù)就可通過(guò)IIS來(lái)存取SQL Server 2000的數(shù)據(jù)庫(kù)了。
![]() ![]() ![]() ![]() |
Pocket PC和桌面PC網(wǎng)絡(luò)連接可以使用Microsoft ActiveSync,也可以使用無(wú)線WiFi 802.1x。由于我們是與單臺(tái)桌面PC連接,需要在其上同時(shí)安裝IIS和SQL Server 2000。實(shí)際使用得知SQL Server CE 2.0運(yùn)行在桌面服務(wù)環(huán)境的服務(wù)器工具與SQL Server 2000在連接上存在一定問(wèn)題,微軟對(duì)此問(wèn)題的解決辦法是:首先將SQL Server 2000打上SP3或者SP4,同時(shí)根據(jù)SQL Server 2000的補(bǔ)丁版本,還需要給SQL Server CE 2.0打上用于SQL Server 2000 SP3或者 SQL Server 2000 SP4的補(bǔ)丁,SQL Server CE的服務(wù)器組件才能順利工作,上述更新和補(bǔ)丁程序在微軟網(wǎng)站上都有下載。
配置結(jié)束后啟動(dòng)Visual Studio .Net 2003,單擊文件 – 新建 – 項(xiàng)目 - Visual Basic 項(xiàng)目 - 智能設(shè)備應(yīng)用程序,創(chuàng)建空項(xiàng)目。整個(gè)程序由一個(gè)Form窗體MainForm組成,其上包含兩個(gè)Panel組件和一個(gè)Button組件,我們把程序分為兩個(gè)主界面,一個(gè)為登錄界面,一個(gè)為操作界面,分別對(duì)應(yīng)兩個(gè)Panel控件,當(dāng)?shù)卿浻肞anel顯示時(shí),操作用Panel則隱藏,當(dāng)?shù)卿洺晒髢蓚€(gè)Panel的顯示屬性則相反。Button控件提供退出操作。登錄用Panel上面包含幾個(gè)TextBox和Button控件供填寫(xiě)SQL Server CE Server Agent 的Web地址、要連接的遠(yuǎn)程SQL Server 2000服務(wù)器名稱(chēng)、能夠存取桌面SQL Server數(shù)據(jù)庫(kù)的用戶(hù)名和密碼,以及要登錄的員工ID和密碼等必要的登錄信息。運(yùn)行在實(shí)際設(shè)備上的圖示如下:
當(dāng)單擊”登錄”按鈕時(shí),程序首先在智能設(shè)備上創(chuàng)建SQL Server CE本地?cái)?shù)據(jù)庫(kù)sdf文件,本程序下載的所有表都保存在該數(shù)據(jù)庫(kù)中:
…… ' 根據(jù)指定的sdf文件路徑創(chuàng)建本地的用戶(hù)數(shù)據(jù)庫(kù)文件用于RDA的PULL en = New SqlCeEngine("Data Source=" & LocalDatabaseFile) en.CreateDatabase() …… |
然后創(chuàng)建RDA對(duì)象的實(shí)例,并填寫(xiě)用于和遠(yuǎn)程SQL Server CE Server Agent 通信的相關(guān)信息。下載允許登錄PPC的合法的用戶(hù)信息數(shù)據(jù)到本地表:
rda.Pull("UserInfo", "Select * from employee where emp_id='" + EMPId + "' and emp_password='" + Password + "'", RemoteConnString, RdaTrackOption.TrackingOff) |
UserInfo表返回的是就是登錄用戶(hù)的記錄信息,請(qǐng)注意RdaTrackOption的值為T(mén)rackingOff,因?yàn)槲覀儧](méi)有在PPC上設(shè)置更改用戶(hù)信息的操作,所以沒(méi)必要跟蹤該表。如果用戶(hù)名和密碼驗(yàn)證通過(guò),UserInfo表的記錄數(shù)就為1,也就是大于0,否則沒(méi)有記錄,然后我們通過(guò)使用SqlCeConnection、SqlCeDataAdapter、SqlCeDataReader以及DataTable返回UserInfo表的所有記錄,一旦記錄數(shù)為0則不允許登錄:
If dtLocalUserInfo.Rows.Count > 0 Then '驗(yàn)證通過(guò) CurrentLogonUserID = dtLocalUserInfo.Rows(0).Item("emp_id").ToString CurrentLogonUserName = dtLocalUserInfo.Rows(0).Item("emp_name").ToString Return True Else '驗(yàn)證失敗,返回false Return False End If |
登錄成功后根據(jù)登錄用戶(hù)名只返回其相關(guān)的任務(wù)記錄,并將任務(wù)記錄保存在名為” itemlist”的表中:
rda.Pull("itemlist", "Select * from itemlist where emp_id='" + EMPId + "'", RemoteConnString, RdaTrackOption.TrackingOnWithIndexes) |
由于RDA不會(huì)保持記錄鎖,push操作會(huì)無(wú)條件的將所有數(shù)據(jù)改動(dòng)都應(yīng)用到SQL Server中,所以容易引起當(dāng)前數(shù)據(jù)庫(kù)的其他用戶(hù)的更新數(shù)據(jù)的丟失。我們需要按照一定的篩選條件過(guò)濾我們感興趣的記錄,以便獲取唯一且不同于其它用戶(hù)返回的記錄集。TrackingOnWithIndexes說(shuō)明在PPC上對(duì)任務(wù)狀態(tài)的更改將會(huì)被跟蹤,在后面的同步操作時(shí)會(huì)根據(jù)跟蹤的變化將更改更新到遠(yuǎn)程數(shù)據(jù)庫(kù)中。
任務(wù)記錄成功獲得后,我們隱藏登錄用Panel而將操作用Panel置于頂層用于對(duì)任務(wù)記錄的添加、狀態(tài)更新、刪除已經(jīng)同步操作等。
用listview控件來(lái)顯示任務(wù)記錄,我們遍歷返回的itemlist表,每一條記錄創(chuàng)建一個(gè)ListViewItem,并添加到listview中以便顯示:
While Reader.Read Dim ls As New ListViewItem(Reader.Item("ID").ToString) ls.SubItems.Add(Trim(Reader.Item("TaskName").ToString)) ls.SubItems.Add(Trim(Reader.Item("TaskContent").ToString)) ls.SubItems.Add(Reader.Item("Finished").ToString) lvItemList.Items.Add(ls) End While |
向SQL Server CE表添加、刪除和更新操作同桌面數(shù)據(jù)庫(kù)操作相似,例如添加操作:
selectCMD.CommandText = "insert into itemlist (ID,TaskName,TaskContent,Finished,EMP_ID) values (" + _ TextBox1.Text + "," + _ "'" + taskname + "'" + "," + _ "'" + taskcontent + "'" + "," + "0" + "," + "'" + CurrentLogonUserID + "'" + ")" selectCMD.CommandTimeout = 30 conn.Open() selectCMD.ExecuteNonQuery() |
對(duì)智能設(shè)備本地表進(jìn)行更新后還需要將改動(dòng)保存到遠(yuǎn)程SQL Server中去,我們使用如下代碼:
rda.Push("itemlist", RemoteConnString, RdaBatchOption.BatchingOn) |
將更改成批推入遠(yuǎn)程SQL Server中,注意:只有跟蹤的提取表才可以執(zhí)行Push操作。運(yùn)行在實(shí)際設(shè)備上的圖示如下:
![]() |
RDA方式同步ce數(shù)據(jù)庫(kù)
首次做移動(dòng)的程序----數(shù)據(jù)同步,感覺(jué)到.net 是如此的方便!?。。?br />
首先,得配置好開(kāi)發(fā)環(huán)境 裝上.net2003 sqlserver2000 以及ce development tols server tools后,新增一個(gè)iis目錄并且配置它為ce server agent端
在瀏覽器中測(cè)試http://localhost/sqlce/sscesa20.dll (sqlce為虛擬目錄名稱(chēng)) 返回server agent幾字,表明配置正確。
下面為程序代碼:
注意:為確保ce中表為可tracked的 故應(yīng)先pull 后執(zhí)行push submit等操作。
1。pull
string InternetServer = "
string InternetUser ="Administrator";
string InternetPassword = "dszj1207";
string RemoteConnection = "Provider=sqloledb;Data Source=DSZJ;Initial Catalog=ce;User Id=sa;Password=winwdr";
string LocalDatabase = "\\My Documents\\rc.sdf";
string LocalConnection = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\\My Documents\\rc.sdf";
string LocalTableName = "students";
string RemoteTableName = "students";
SqlCeRemoteDataAccess rda = new SqlCeRemoteDataAccess(InternetServer, InternetUser, InternetPassword, LocalConnection);
rda.Pull(LocalTableName,"select * from students", RemoteConnection, RdaTrackOption.TrackingOnWithIndexes, "rdaErrors");
rda.Dispose();
}
2。push
SqlCeRemoteDataAccess rda = null;
try
{
rda = new SqlCeRemoteDataAccess();
rda.InternetLogin="Administrator";
rda.InternetPassword="dszj1207";
rda.InternetUrl = "
rda.LocalConnectionString = "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\\My Documents\\rc.sdf";
rda.Push("students", rdaOleDbConnectString, RdaBatchOption.BatchingOff);
}
catch(SqlCeException ex)
{
MessageBox.Show(ex.ToString(), "Error");
}
finally
{
rda.Dispose();
}
3.。submit
SqlCeRemoteDataAccess rda = null;
try
{
rda = new SqlCeRemoteDataAccess(InternetServer, InternetUser, InternetPassword, LocalConnection);
rda.SubmitSql("insert into students values('sunjiguang','010547896321','天津')",RemoteConnection);
}
catch(SqlCeException ex)
{
MessageBox.Show(ex.ToString(), "Error");
}
finally
{
rda.Dispose();
}
---------------------------------------------------------
專(zhuān)注移動(dòng)開(kāi)發(fā)
Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian