http://www.51testing.com/html/11/586.html
基于SQL Server CE的移动服务系统开发
| |
文章出处:转载 作者:侯月文 发布时间:2005-11-04
| |
移动服务是应用比较广泛的移动解决方案,其核心是利用移动计算和无线通信技术为企业现场服务人员提供全面、便捷、实时的信息服务。我们现在就为某电器制造商设计一套用于售后维修服务的移动解决方案。
该电器制造商目前售后维修服务的基本工作流程是:客户打电话报修,呼叫中心记录用户的基本信息(如姓名、地址和电话等等)和客户对故障的描述信息,生成维修单,维修服务人员领取维修单,维修服务人员上门为客户服务,填写维修记录单(如实际故障,维修所用零部件,维修所用时间等),客户签字认可,维修服务人员交回维修记录单,呼叫中心电话回访客户。 采用移动服务系统改造后的工作流程是:客户打电话报修,呼叫中心记录用户的基本信息和客户对故障的描述信息,生成维修单,维修单通过无线网络直接发送到维修服务人员的手持设备上,维修服务人员上门为客户服务,在移动设备上填写维修记录单,客户在移动设备上签字认可,维修服务人员把维修记录单通过无线网络发回至呼叫中心,呼叫中心电话回访客户。 通过上述新旧流程的对比,可以发现采用移动服务系统之后将显著的提升维修服务人员的工作效率,大大缩短客户报修之后的响应时间,对于提升售后服务的质量和客户满意度都有极大的益处。 移动服务系统设计移动数据库SQL Server CE因为移动服务系统需要下载维修单到移动设备上,并在移动设备上临时保存维修单,所以在移动设备上需要有一个数据库系统。我们选择的移动数据库系统是SQL Server CE。 Microsoft SQL 2000 Windows CE Edition(又称为SQL Server CE)是用于移动设备上的小型关系数据库。SQL Server CE的发展历程从1.0开始,当时.NET的技术框架还不能应用到移动设备上,这个时候大家在开发基于数据库的移动应用时,采用的是Embedded Visual Tools 3.0中的VB或VC++,使用OLE DB for SQL Server CE或ADOCE访问SQL Server CE数据库。随着.NET Compact Framework的推出,SQL Server CE也推出了2.0,2.0加入了更多的新功能,并在很多性能参数都有较大的提高,但更重要的是从此可以在Visual Studio .NET中通过ADO.NET访问SQL Server CE的数据库了。 SQL Server CE与我们熟悉的其他关系数据库相比,有以下的特点: 1) 打开SQL Server CE数据库时,是通过指定其数据库文件所在的完整路径来打开的。例如,当在EVB中使用ADOCE打开数据库时,可以用下面的形式: Dim cn As ADOCE.Connection 2) SQL Server CE支持数据库密码和数据库文件加密 例如,当使用.NET Compact Framework中的SqlCeConnection.Open方法打开数据库时,可以使用如下的连接字符串: "data source=\NorthWind.sdf; password=" 当使用ADOCE时,则在连接字符串中必须指定SSCE:Database Password连接属性。 "Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0; data source=\NorthWind.sdf; SSCE:Database Password=" 3) SQL Server CE同样支持大量的内部函数,这些函数包括数学函数、字符串函数和内部函数等。 4) SQL Server CE 2.0 通过 ADO.NET 增加了对参数化查询的支持。 例如,我们在构造SQL语句时,可以构造以下的语句,然后再利用ADO.NET的机制替换“?”所代表的参数。对参数化查询的支持是 SQL Server CE 2.0的新功能。 "INSERT INTO TableA (col1, col2) VALUES (?, ?)" 5) 与先前版本的SQL Server CE相比,新版本的另一个改进是加入了更加可靠的错误处理功能。SQL Server CE增加了一个名为SqlCeException的新类,这个类允许您捕捉本机SQL Server CE错误并适当地处理它们。 6) SQL Server CE 2.0提供了两种基本方法来连接后端SQL Server数据库:RDA和合并复制。RDA访问功能支持与SQL Server 7.0(和更高版本)数据库的连接,合并复制要求后端必须是SQL Server 2000。 |
数据同步设计
移动服务系统需要下载呼叫中心产生的维修单,也需要把维修服务人员填写的维修记录单上传到呼叫中心,因此移动服务系统需要与呼叫中心进行双向的数据同步。
SQL Server CE与SQL Server之间可以通过RDA和Replication(合并复制)两种方式进行数据同步。RDA适用于简单的、不需要全功能的合并复制功能(例如数据冲突处理)的数据同步,而Replication则基于Windows Server 2000的合并复制功能,可以完成更多更复杂的功能。
RDA全称是Remote data access,其主要由三部分组成:SQL Server CE数据库引擎、SQL Server CE客户端代理和SQL Server CE服务器端代理。SQL Server CE数据库引擎负责写入和读取SQL Server CE数据库中的数据;SQL Server CE客户端代理是RDA在移动设备上的主要组件,它实现了RDA的主要功能,我们可以通过程序调用它提供的接口以控制RDA;SQL Server CE服务器端代理位于服务器端,它与SQL Server CE客户端代理通过HTTP协议进行通信,接收并处理SQL Server CE客户端代理的命令。
RDA支持三个主要的方法,他们分别是:
- Pull
将SQL Server 2000数据库中的表“拉”到SQL Server CE中。在调用此方法时,可以设置数据跟踪选项,如果设置数据跟踪,则SQL Server CE数据库引擎会自动跟踪对数据的插入、修改和删除操作。 - Push
如果在Pull时设置了数据跟踪选项,可以将SQL Server CE中的数据“推”回到SQL Server 2000中。在SQL Server CE中对数据的任何修改都会反映到SQL Server 2000中。 - SubmitSQL
直接向SQL Server 2000数据库提交一个命令。
图1 SQL Server CE与SQL Server数据同步示意图合并复制是RDA的一种替代方案,只能与SQL Server 2000配合使用。合并复制的工作组成与RDA基本类似,但是在服务器端多了一个SQL Server CE复制提供程序,也就是说SQL Server CE服务器端代理通过调用SQL Server CE复制提供程序,从SQL Server数据库中选取一个“快照”返回给SQL Server CE客户端代理,客户端代理在设备上建立SQL Server CE的数据库(订阅数据库)。对订阅数据库的任何修改都会被SQL Server CE数据库引擎记录下来,在调用同步方法时,可以把这些修改作用到后台SQL Server数据库中。
移动服务系统在下载维修单时,要满足两个基本的条件:一是用户只能下载分配给自己的维修单;二是只能下载尚没有完成的维修单。在上传维修记录单时,也要满足两个基本条件:一是只能上传客户已经签名确认的维修记录单;二是只能上传维修服务人员选定的维修记录单。由此可见,移动服务系统在数据同步时,需要实现一定的义务逻辑规则,如果用RDA或合并复制实现这些业务逻辑规则,会比较麻烦一些,所以我们设计如下的数据同步规则:
- 数据同步包括两个部分:移动端和服务器端
- 服务器端采用IIS+ASP.NET构建应用服务器
- 移动端与服务器端采用HTTP协议传输数据
- 移动端采用类似http://host/do.aspx?action=GetJobList&user=&date=的URL访问服务器端
- 服务器端返回数据时,以SUCCESS表示成功,FAILED表示失败,记录之间以“^”为分隔符,字段之间以“|”为分隔符
- 移动端解析服务器端返回数据,如果需要的话更新SQL Server CE数据库
开发准备工作
准备开发环境
移动服务系统采用Visual Studio .NET开发,如果要开发基于SQL Server CE的应用,只需要在项目中添加System.Data.SqlServerCe的引用,在运行和部署时系统会自动安装两个SQL Server CE的安装包文件,他们是sqlce.dev.wce4.armv4.CAB和sqlce.wce4.armv4.CAB(armv4这一项会根据不同的平台而有所不同)。sqlce.dev.wce4.armv4.CAB包括Isqlw20.exe和两个错误字符串文件Ssceerror20en.dll和Msdaeren.dll,他们将被安装到移动设备的\Program Files\SQLCE 2.0目录;sqlce.wce4.armv4.CAB包括将被安装到\Program Files\SQLCE 2.0目录下的Ssce20.dll、Ssceca20.dll和安装到\windows目录下的Sscemw20.dll。
isqlw20.exe是SQL Server CE的查询分析器程序,是SQL Server CE在移动设备上的主要管理工具。
图2 SQL Server CE查询分析器通过查询分析器,我们可以建立新的SQL Server CE数据库,打开和关闭数据库,在数据库中建立、删除和维护数据表,维护索引信息,可以输入SQL语句并查看执行结果。
准备SQL Server CE数据库
在开发中使用的SQL Server CE数据库,可以通过三种方式建立:
- 通过isqlw20.exe查询分析器程序建立
- 通过编写程序建立数据库,建立表,插入必要的数据
- 通过RDA或合并复制建立
其中,通过RDA方式建立是最容易的方法,因为我们可以先行在SQL Server 2000中建立数据库,设计表结构,插入必要的数据,然后通过RDA一次性的把SQL Server 2000中的表和数据下载到移动设备上。
1) 安装SQL Server CE
首先安装SQL Server 2000,安装完成后,还需要安装SP3a或者最新的SP4补丁。如果希望通过RDA或合并复制与SQL Server 2000进行数据同步,那么还必须下载SQL Server CE的补丁。SQL Server CE的补丁应该与SQL Server 2000的补丁是一致的,如果SQL Server 2000的补丁是SP3a,那么需要下载SQL Server CE的SP3a的补丁。 SQL Server CE安装包、SQL Server CE的SP3a补丁及SQL Server CE的SP4补丁均可在微软的网站(http://www.microsoft.com/downloads/)下载。
下载完成后,首先安装SQL Server CE的安装程序,然后再安装SQL Server CE的补丁程序。
2) 配置RDA因为RDA使用HTTP协议实现数据通信,所以服务器端首先需要安装并配置好IIS服务。在“开始”菜单中运行“Configure Connectivity Support in IIS”启动SQL Server CE连接配置程序。
图3 启动SQL Server CE连接配置出现“SQL Server CE Connectivity Management”界面,双击“Create a Virtual Directory”打开配置向导。在图4的窗口中输入虚拟目录的别名。
图4 SQL Server CE连接管理配置向导在图5的界面中选择必要的安全设置,可以按照业务的实际需求情况选择,如果不需要额外安全设置,可以选择允许匿名访问。
图5 安全设置配置设置完成后,打开浏览器,输入:
http://localhost/sqlce/sscesa20.dll
如果以上设置正确,应该可以出现图6所示的文字:
图6 设置完毕浏览器效果图3) 下载数据库
使用isqlw20.exe查询分析器程序建立一个空的数据库:MobileService.sdf。
建立空数据库也可以使用下面的代码建立:
if (File.Exists ("\\MobileService.sdf") )
File.Delete ("\\MobileService.sdf");
SqlCeEngine engine = new SqlCeEngine ("Data Source = \\ MobileService;password=test;encrypt database=TRUE");
engine.CreateDatabase ();
engine.Dispose();首先判断\MobileService.sdf文件是否已经存在,如果已经存在,则先删除该文件。在创建数据库时,用的是SqlCeEngine类的CreateDatabase方法,CreateDatabase会根据LocalConnectionString属性表示的连接字符串创建SQL Server CE数据库。在连接字符串中的password和encrypt database 属性是可选项,但是如果使用了encrypt database 属性则必须包含password属性。SqlCeEngine类还有一个很重要的方法是Compact,Compact方法用于回收SQL Server CE数据库中浪费的空间,可用于更改SQL Server CE数据库的排列顺序、加密方式或密码。
在Visual Studio .NET中建立一个简单的移动应用程序,执行下面的代码就可以通过RDA的Pull方法在移动设备上建立JOB表,并下载SQL Server中JOB表的数据。通过更换不同的表名称,就可以循环下载SQL Server中所有的表。
string rdaOleDbConnectString = "Provider=sqloledb; Data Source=10.1.11.18;Initial Catalog=test; User Id=sa;Password=sa";
SqlCeRemoteDataAccess rda = null;
rda = new SqlCeRemoteDataAccess();
rda.InternetLogin = "MyLogin";
rda.InternetPassword = "";
rda.InternetUrl = "http://10.1.11.18/sqlce/sscesa20.dll";
rda.LocalConnectionString = @"Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;Data Source=\MobileService.sdf";
rda.Pull(
"JOB",
"Select * from JOB",
rdaOleDbConnectString);在使用SqlCeRemoteDataAccess访问RDA时,需要指定三个重要的参数:
- SQL Server CE服务器端代理的访问地址,通过SqlCeRemoteDataAccess类的InternetUrl属性指定;
- 连接到SQL Server CE数据库的连接字符串,通过SqlCeRemoteDataAccess类的LocalConnectionString 属性指定;
- SQL Server CE服务器端代理访问SQL数据库的连接字符串,通过调用Pull、Push或Submit方法时指定
另外,如果在服务器端设置时需要用户登录,还需要设置InternetLogin属性和InternetPassword属性;如果通过代理访问服务器,还需要指定相关的代理属性。
Pull方法中的第一个参数是指定的本地表名称,如果该名称的表已经在SQL Server CE数据库中存在,则该方法会出错;第四个参数是设置是否打开数据跟踪选项的,如果设置为不打开跟踪选项,则第二个参数指定的SQL语句可以从多个表中提取数据,否则只能从单个表中提取数据。因为我们只是要下载数据,并不打算采用Push方法上传数据,所以在此我们可以不指定第四个参数。
Push方法把SQL Server CE表中的更改传送回SQL Server表,应用程序必须已经通过调用Pull方法并将RdaTrackOption设置为TrackingOn或TrackingOnWithIndexes创建了SQL Server CE的数据表。
SubmitSQL提交在远程SQL Server的数据库上执行的SQL语句。它所提交的SQL语句必须是不返回任何数据行的SQL语句。
开发移动服务应用程序
下载维修单数据
下载维修单需要两个参数:当前的用户名和最后一个维修单的时间。先通过查询数据库得到最后一个维修单的时间。
SqlCeConnection conn = null;
try
{
conn = new SqlCeConnection ("Data Source = \\MobileService.sdf;password=test;encrypt database=TRUE");
conn.Open();
//查询当前job中最后一个job的时间
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "select max(jobtime) from job";
SqlCeDataReader dtr = cmd.ExecuteReader(CommandBehavior.SingleResult);
string latestdate = "";
while (dtr.Read())
{
if(dtr.IsDBNull(0))
{
latestdate = "2005-04-15 0:0:0";
}
else
{
latestdate = dtr.GetDateTime(0).ToString();
}
}
dtr.Close();
}
catch(SqlCeException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if(conn.State == ConnectionState.Open)
conn.Close();
}
使用SqlCeConnection类Open方法打开SQL Server CE数据库的一个连接。一个SQL Server CE数据库仅能打开一个唯一的连接,所以在使用时要注意试图打开多个到数据库的连接是不会成功的。但是,多个SQL Server CE的命令可以共享同一个打开的连接。使用Open方法打开的连接不会自动关闭,所以必须显式关闭该连接。
然后使用SqlCeCommand类的ExecuteReader方法执行了一条SELECT语句,并将执行结果保存到SqlCeDataReader类中,然后用Read方法读取该记录。SELECT语句用到了SQL Server CE的内置函数max,可以得到最大的一个日期。
在使用Read方法读取记录时,先使用IsDBNull方法判断是否为空,如果job表中原本就没有记录的话,使用max函数得到的结果为空。如果不为空的话,再调用GetDateTime方法得到结果集中的DateTime格式的值。
//下载维修单
string url ="http://10.1.11.18/MSWEB/Do.aspx?action=GetJobList&user=123&date="+latestdate;
HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url);
HttpWebResponse result = (HttpWebResponse) req.GetResponse();
Stream ReceiveStream = result.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("GB2312");
StreamReader sr = new StreamReader(ReceiveStream,encode);
string resultstring = sr.ReadToEnd();
ReceiveStream.Close();
sr.Close();
首先用用户名和最后的维修单时间构造一个URL,然后通过HttpWebRequest类的Create方法打开这个URL,通过HttpWebResponse接收返回的数据,使用Stream读取返回流中的数据。最后的结果保存在resultstring变量中。
按照设计的数据同步规则解析保存在resultstring变量中的记录和字段(代码略),然后把记录写入SQL Server CE数据库。
//写入数据库
cmd.CommandText = "INSERT INTO JOB(id,jobname,jobdesc,jobtime,useraddress,userphone)"
+"VALUES (<各字段数据>)";
cmd.ExecuteNonQuery();
使用SqlCeCommand类的ExecuteNonQuery方法执行不需要返回行记录的SQL语句。
显示维修单列表
在.NET Compact Framework中仍然支持数据绑定控件,因此我们在实现维修单列表时,采用DataGrid数据绑定列表控件。在窗口中创建DataGrid控件,命名为dataGridJobList,然后在属性窗口中单击TableStyles项的“…”图标,将出现TableStyles集合编辑器,如图7所示:
图7 TableStyles集合编辑器
在MappingName中输入“JOBLIST”,点击GridColumSytles旁边的“...”按钮,设定数据绑定的列映射。在设定列映射时,添加三列,映射名称分别是id,jobname,jobtime。如图8所示:
图8 列映射效果图
在Form_load事件中添加数据绑定的代码:
//数据绑定
this.dataGridJobList.RowHeadersVisible = false;
dataGridJobList.Font = new Font("宋体",9F,FontStyle.Regular );
System.Data.DataSet dsJobList;
System.Data.DataTable dtJobList;
dsJobList = new DataSet();
sql = "select id,jobname,jobtime from job order by jobtime desc";
SqlCeDataAdapter adapter = new SqlCeDataAdapter(sql, conn);
adapter.Fill(dsJobList, "JOBLIST");
dtJobList = dsJobList.Tables["JOBLIST"];
this.dataGridJobList.DataSource = dtJobList;
通过SqlCeDataAdapter的Fill方法把SQL语句的执行结果填充到DataSet中,取出DataSet中名为“JOBLIST”的DataTable,把DataGrid控件的数据源属性DataSource设定为名称为“JOBLIST”的DataTable。通过上述操作就可以完成SQL Server CE数据与一个DataGrid控件的数据绑定。
编辑并保存维修记录单
当点击列表中的维修单时,将弹出维修记录编辑界面。在DataGrid的MouseUP事件中添加下列代码将可以获取当前点击的是哪一个维修单,并打开维修记录编辑界面。
DataGrid myGrid = (DataGrid)sender;
DataGrid.HitTestInfo myHitInfo = myGrid.HitTest(e.X,e.Y);
if (myHitInfo.Type == DataGrid.HitTestType.Cell && myHitInfo.Column == 1)
{
Cursor.Current = Cursors.WaitCursor;
DataGridCell myCell = dataGridJobList.CurrentCell;
string jobid = dtJobList.Rows[myCell.RowNumber][0].ToString();
Cursor.Current = Cursors.Default;
FrmJob frmJob = new FrmJob(jobid);
frmJob.ShowDialog();
}
在FrmJob的Load事件中添加根据jobid查询维修单详细信息的代码,并将查询结果显示在界面上。
string sql ="select jobname,jobdesc,jobtime,userphone,useraddress,jobdonedesc from job where id="+jobid;
SqlCeCommand cmdDML = new SqlCeCommand(sql,conn);
cmdDML.CommandType = CommandType.Text;
SqlCeDataReader dtr = cmdDML.ExecuteReader(CommandBehavior.SingleResult);
while (dtr.Read())
{
this.lblJobName.Text = dtr.GetString(0);
this.lblJobDesc.Text = dtr.GetString(1);
this.lblJobTime.Text = dtr.GetDateTime(2).ToString();
this.lblPhone.Text = dtr.GetString(3);
this.lblAddress.Text = dtr.GetString(4);
if(!dtr.IsDBNull(5))
this.txtDoneDesc.Text = dtr.GetString(5);
}
dtr.Close();
编辑完成后,使用SqlCeCommand类的ExecuteNonQuery方法执行UPDATE语句更新维修记录单。
上传维修记录单
上传维修记录单时采用的方法与下载基本相同,需要在后台服务器添加一个新的上传接口。需要注意的是,因为HTTP的GET协议的URL长度通常是有限制的,所以如果需要上传的内容比较多时,需要考虑用POST协议。
结束语
本文结合移动服务系统的开发过程介绍了SQL Server CE的特点以及安装、开发SQL Server CE应用程序的方法,如果需要更全面和详尽的了解SQL Server CE,可以参阅SQL Server CE附带的“Books Onlie”。
通过本文的介绍,大家可以看到利用ADO.NET开发SQL Server CE的应用程序,在开发方法上与在PC平台上使用ADO.NET非常类似,但总的说来还是要注意一下几点:
- SQL Server CE是用于移动设备上的一个很轻量级的数据库系统,其性能受移动设备的存储能力和计算能力的制约,因此在使用SQL Server CE时,尽量避免大数据量的操作,要尽可能的压缩SQL Server CE上数据的规模。
- SQL Server CE有一些比较特殊的地方需要注意,例如只能打开一个到SQL Server CE的连接,支持数据库口令和加密,支持部分函数等。
- 在使用RDA或合并复制时,要结合自己的数据同步业务逻辑灵活运用,避免生搬硬套带来更多的不方便。
- 注意使用SqlCeEngine类的Compact方法回收 SQL Server CE 数据库中浪费的空间。如果发现数据库文件已经达到几兆甚至将近十兆左右时,可以用Compact方法尝试压缩一下数据库。