基于SQLServerCE的移动服务系统开发教学内容.doc
Good is good, but better carries it.精益求精,善益求善。基于SQLServerCE的移动服务系统开发-基于SQLServerCE的移动服务系统开发Author:侯月文转载时间:2006-09-13.文章来源:移动服务系统分析与设计移动服务系统需求分析移动服务是应用比较广泛的移动解决方案,其核心是利用移动计算和无线通信技术为企业现场服务人员提供全面、便捷、实时的信息服务。我们现在就为某电器制造商设计一套用于售后维修服务的移动解决方案。该电器制造商目前售后维修服务的基本工作流程是:客户打电话报修,呼叫中心记录用户的基本信息(如姓名、地址和电话等等)和客户对故障的描述信息,生成维修单,维修服务人员领取维修单,维修服务人员上门为客户服务,填写维修记录单(如实际故障,维修所用零部件,维修所用时间等),客户签字认可,维修服务人员交回维修记录单,呼叫中心电话回访客户。采用移动服务系统改造后的工作流程是:客户打电话报修,呼叫中心记录用户的基本信息和客户对故障的描述信息,生成维修单,维修单通过无线网络直接发送到维修服务人员的手持设备上,维修服务人员上门为客户服务,在移动设备上填写维修记录单,客户在移动设备上签字认可,维修服务人员把维修记录单通过无线网络发回至呼叫中心,呼叫中心电话回访客户。通过上述新旧流程的对比,可以发现采用移动服务系统之后将显著的提升维修服务人员的工作效率,大大缩短客户报修之后的响应时间,对于提升售后服务的质量和客户满意度都有极大的益处。移动服务系统设计移动数据库SQLServerCE因为移动服务系统需要下载维修单到移动设备上,并在移动设备上临时保存维修单,所以在移动设备上需要有一个数据库系统。我们选择的移动数据库系统是SQLServerCE。MicrosoftSQL2000WindowsCEEdition(又称为SQLServerCE)是用于移动设备上的小型关系数据库。SQLServerCE的发展历程从1.0开始,当时.NET的技术框架还不能应用到移动设备上,这个时候大家在开发基于数据库的移动应用时,采用的是EmbeddedVisualTools3.0中的VB或VC+,使用OLEDBforSQLServerCE或ADOCE访问SQLServerCE数据库。随着.NETCompactFramework的推出,SQLServerCE也推出了2.0,2.0加入了更多的新功能,并在很多性能参数都有较大的提高,但更重要的是从此可以在VisualStudio.NET中通过ADO.NET访问SQLServerCE的数据库了。SQLServerCE与我们熟悉的其他关系数据库相比,有以下的特点:1)打开SQLServerCE数据库时,是通过指定其数据库文件所在的完整路径来打开的。例如,当在EVB中使用ADOCE打开数据库时,可以用下面的形式:DimcnAsADOCE.ConnectionSetcn=CreateObject("ADOCE.Connection.3.1")cn.ConnectionString="Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;datasource=Northwind.sdf"cn.Open2)SQLServerCE支持数据库密码和数据库文件加密例如,当使用.NETCompactFramework中的SqlCeConnection.Open方法打开数据库时,可以使用如下的连接字符串:"datasource=NorthWind.sdf;password=<myPassword>"当使用ADOCE时,则在连接字符串中必须指定SSCE:DatabasePassword连接属性。"Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;datasource=NorthWind.sdf;SSCE:DatabasePassword=<myPassword>"3)SQLServerCE同样支持大量的内部函数,这些函数包括数学函数、字符串函数和内部函数等。4)SQLServerCE2.0通过ADO.NET增加了对参数化查询的支持。例如,我们在构造SQL语句时,可以构造以下的语句,然后再利用ADO.NET的机制替换“?”所代表的参数。对参数化查询的支持是SQLServerCE2.0的新功能。"INSERTINTOTableA(col1,col2)VALUES(?,?)"5)与先前版本的SQLServerCE相比,新版本的另一个改进是加入了更加可靠的错误处理功能。SQLServerCE增加了一个名为SqlCeException的新类,这个类允许您捕捉本机SQLServerCE错误并适当地处理它们。6)SQLServerCE2.0提供了两种基本方法来连接后端SQLServer数据库:RDA和合并复制。RDA访问功能支持与SQLServer7.0(和更高版本)数据库的连接,合并复制要求后端必须是SQLServer2000。数据同步设计移动服务系统需要下载呼叫中心产生的维修单,也需要把维修服务人员填写的维修记录单上传到呼叫中心,因此移动服务系统需要与呼叫中心进行双向的数据同步。SQLServerCE与SQLServer之间可以通过RDA和Replication(合并复制)两种方式进行数据同步。RDA适用于简单的、不需要全功能的合并复制功能(例如数据冲突处理)的数据同步,而Replication则基于WindowsServer2000的合并复制功能,可以完成更多更复杂的功能。RDA全称是Remotedataaccess,其主要由三部分组成:SQLServerCE数据库引擎、SQLServerCE客户端代理和SQLServerCE服务器端代理。SQLServerCE数据库引擎负责写入和读取SQLServerCE数据库中的数据;SQLServerCE客户端代理是RDA在移动设备上的主要组件,它实现了RDA的主要功能,我们可以通过程序调用它提供的接口以控制RDA;SQLServerCE服务器端代理位于服务器端,它与SQLServerCE客户端代理通过HTTP协议进行通信,接收并处理SQLServerCE客户端代理的命令。RDA支持三个主要的方法,他们分别是:Pull将SQLServer2000数据库中的表“拉”到SQLServerCE中。在调用此方法时,可以设置数据跟踪选项,如果设置数据跟踪,则SQLServerCE数据库引擎会自动跟踪对数据的插入、修改和删除操作。Push如果在Pull时设置了数据跟踪选项,可以将SQLServerCE中的数据“推”回到SQLServer2000中。在SQLServerCE中对数据的任何修改都会反映到SQLServer2000中。SubmitSQL直接向SQLServer2000数据库提交一个命令。图1SQLServerCE与SQLServer数据同步示意图合并复制是RDA的一种替代方案,只能与SQLServer2000配合使用。合并复制的工作组成与RDA基本类似,但是在服务器端多了一个SQLServerCE复制提供程序,也就是说SQLServerCE服务器端代理通过调用SQLServerCE复制提供程序,从SQLServer数据库中选取一个“快照”返回给SQLServerCE客户端代理,客户端代理在设备上建立SQLServerCE的数据库(订阅数据库)。对订阅数据库的任何修改都会被SQLServerCE数据库引擎记录下来,在调用同步方法时,可以把这些修改作用到后台SQLServer数据库中。移动服务系统在下载维修单时,要满足两个基本的条件:一是用户只能下载分配给自己的维修单;二是只能下载尚没有完成的维修单。在上传维修记录单时,也要满足两个基本条件:一是只能上传客户已经签名确认的维修记录单;二是只能上传维修服务人员选定的维修记录单。由此可见,移动服务系统在数据同步时,需要实现一定的义务逻辑规则,如果用RDA或合并复制实现这些业务逻辑规则,会比较麻烦一些,所以我们设计如下的数据同步规则:数据同步包括两个部分:移动端和服务器端服务器端采用IIS+ASP.NET构建应用服务器移动端与服务器端采用HTTP协议传输数据移动端采用类似http:/host/do.aspx?action=GetJobList&user=&date=的URL访问服务器端服务器端返回数据时,以SUCCESS表示成功,FAILED表示失败,记录之间以“”为分隔符,字段之间以“|”为分隔符移动端解析服务器端返回数据,如果需要的话更新SQLServerCE数据库开发准备工作准备开发环境移动服务系统采用VisualStudio.NET开发,如果要开发基于SQLServerCE的应用,只需要在项目中添加System.Data.SqlServerCe的引用,在运行和部署时系统会自动安装两个SQLServerCE的安装包文件,他们是sqlce.dev.wce4.armv4.CAB和sqlce.wce4.armv4.CAB(armv4这一项会根据不同的平台而有所不同)。sqlce.dev.wce4.armv4.CAB包括Isqlw20.exe和两个错误字符串文件Ssceerror20en.dll和Msdaeren.dll,他们将被安装到移动设备的ProgramFilesSQLCE2.0目录;sqlce.wce4.armv4.CAB包括将被安装到ProgramFilesSQLCE2.0目录下的Ssce20.dll、Ssceca20.dll和安装到windows目录下的Sscemw20.dll。isqlw20.exe是SQLServerCE的查询分析器程序,是SQLServerCE在移动设备上的主要管理工具。图2SQLServerCE查询分析器通过查询分析器,我们可以建立新的SQLServerCE数据库,打开和关闭数据库,在数据库中建立、删除和维护数据表,维护索引信息,可以输入SQL语句并查看执行结果。准备SQLServerCE数据库在开发中使用的SQLServerCE数据库,可以通过三种方式建立:通过isqlw20.exe查询分析器程序建立通过编写程序建立数据库,建立表,插入必要的数据通过RDA或合并复制建立其中,通过RDA方式建立是最容易的方法,因为我们可以先行在SQLServer2000中建立数据库,设计表结构,插入必要的数据,然后通过RDA一次性的把SQLServer2000中的表和数据下载到移动设备上。1)安装SQLServerCE首先安装SQLServer2000,安装完成后,还需要安装SP3a或者最新的SP4补丁。如果希望通过RDA或合并复制与SQLServer2000进行数据同步,那么还必须下载SQLServerCE的补丁。SQLServerCE的补丁应该与SQLServer2000的补丁是一致的,如果SQLServer2000的补丁是SP3a,那么需要下载SQLServerCE的SP3a的补丁。SQLServerCE安装包、SQLServerCE的SP3a补丁及SQLServerCE的SP4补丁均可在微软的网站(下载完成后,首先安装SQLServerCE的安装程序,然后再安装SQLServerCE的补丁程序。2)配置RDA因为RDA使用HTTP协议实现数据通信,所以服务器端首先需要安装并配置好IIS服务。在“开始”菜单中运行“ConfigureConnectivitySupportinIIS”启动SQLServerCE连接配置程序。图3启动SQLServerCE连接配置出现“SQLServerCEConnectivityManagement”界面,双击“CreateaVirtualDirectory”打开配置向导。在图4的窗口中输入虚拟目录的别名。图4SQLServerCE连接管理配置向导在图5的界面中选择必要的安全设置,可以按照业务的实际需求情况选择,如果不需要额外安全设置,可以选择允许匿名访问。图5安全设置配置设置完成后,打开浏览器,输入:http:/localhost/sqlce/sscesa20.dll如果以上设置正确,应该可以出现图6所示的文字:图6设置完毕浏览器效果图3)下载数据库使用isqlw20.exe查询分析器程序建立一个空的数据库:MobileService.sdf。建立空数据库也可以使用下面的代码建立:if(File.Exists("MobileService.sdf") File.Delete("MobileService.sdf");SqlCeEngineengine=newSqlCeEngine("DataSource=MobileService;password=test;encryptdatabase=TRUE");engine.CreateDatabase();engine.Dispose();首先判断MobileService.sdf文件是否已经存在,如果已经存在,则先删除该文件。在创建数据库时,用的是SqlCeEngine类的CreateDatabase方法,CreateDatabase会根据LocalConnectionString属性表示的连接字符串创建SQLServerCE数据库。在连接字符串中的password和encryptdatabase属性是可选项,但是如果使用了encryptdatabase属性则必须包含password属性。SqlCeEngine类还有一个很重要的方法是Compact,Compact方法用于回收SQLServerCE数据库中浪费的空间,可用于更改SQLServerCE数据库的排列顺序、加密方式或密码。在VisualStudio.NET中建立一个简单的移动应用程序,执行下面的代码就可以通过RDA的Pull方法在移动设备上建立JOB表,并下载SQLServer中JOB表的数据。通过更换不同的表名称,就可以循环下载SQLServer中所有的表。stringrdaOleDbConnectString="Provider=sqloledb;DataSource=10.1.11.18;InitialCatalog=test;UserId=sa;Password=sa"SqlCeRemoteDataAccessrda=null;rda=newSqlCeRemoteDataAccess();rda.InternetLogin="MyLogin"rda.InternetPassword="<password>"rda.InternetUrl="http:/10.1.11.18/sqlce/sscesa20.dll"rda.LocalConnectionString="Provider=Microsoft.SQLSERVER.OLEDB.CE.2.0;DataSource=MobileService.sdf"rda.Pull( "JOB", "Select*fromJOB", rdaOleDbConnectString);在使用SqlCeRemoteDataAccess访问RDA时,需要指定三个重要的参数:SQLServerCE服务器端代理的访问地址,通过SqlCeRemoteDataAccess类的InternetUrl属性指定;连接到SQLServerCE数据库的连接字符串,通过SqlCeRemoteDataAccess类的LocalConnectionString属性指定;SQLServerCE服务器端代理访问SQL数据库的连接字符串,通过调用Pull、Push或Submit方法时指定另外,如果在服务器端设置时需要用户登录,还需要设置InternetLogin属性和InternetPassword属性;如果通过代理访问服务器,还需要指定相关的代理属性。Pull方法中的第一个参数是指定的本地表名称,如果该名称的表已经在SQLServerCE数据库中存在,则该方法会出错;第四个参数是设置是否打开数据跟踪选项的,如果设置为不打开跟踪选项,则第二个参数指定的SQL语句可以从多个表中提取数据,否则只能从单个表中提取数据。因为我们只是要下载数据,并不打算采用Push方法上传数据,所以在此我们可以不指定第四个参数。Push方法把SQLServerCE表中的更改传送回SQLServer表,应用程序必须已经通过调用Pull方法并将RdaTrackOption设置为TrackingOn或TrackingOnWithIndexes创建了SQLServerCE的数据表。SubmitSQL提交在远程SQLServer的数据库上执行的SQL语句。它所提交的SQL语句必须是不返回任何数据行的SQL语句。开发移动服务应用程序下载维修单数据下载维修单需要两个参数:当前的用户名和最后一个维修单的时间。先通过查询数据库得到最后一个维修单的时间。SqlCeConnectionconn=null;try conn=newSqlCeConnection("DataSource=MobileService.sdf;password=test;encryptdatabase=TRUE"); conn.Open(); /查询当前job中最后一个job的时间 SqlCeCommandcmd=conn.CreateCommand(); cmd.CommandText="selectmax(jobtime)fromjob" SqlCeDataReaderdtr=cmd.ExecuteReader(CommandBehavior.SingleResult); stringlatestdate="" while(dtr.Read() if(dtr.IsDBNull(0) latestdate="2005-04-150:0:0" else latestdate=dtr.GetDateTime(0).ToString(); dtr.Close();catch(SqlCeExceptionex) MessageBox.Show(ex.Message);finally if(conn.State=ConnectionState.Open) conn.Close();使用SqlCeConnection类Open方法打开SQLServerCE数据库的一个连接。一个SQLServerCE数据库仅能打开一个唯一的连接,所以在使用时要注意试图打开多个到数据库的连接是不会成功的。但是,多个SQLServerCE的命令可以共享同一个打开的连接。使用Open方法打开的连接不会自动关闭,所以必须显式关闭该连接。然后使用SqlCeCommand类的ExecuteReader方法执行了一条SELECT语句,并将执行结果保存到SqlCeDataReader类中,然后用Read方法读取该记录。SELECT语句用到了SQLServerCE的内置函数max,可以得到最大的一个日期。在使用Read方法读取记录时,先使用IsDBNull方法判断是否为空,如果job表中原本就没有记录的话,使用max函数得到的结果为空。如果不为空的话,再调用GetDateTime方法得到结果集中的DateTime格式的值。/下载维修单stringurl="http:/10.1.11.18/MSWEB/Do.aspx?action=GetJobList&user=123&date="+latestdate;HttpWebRequestreq=(HttpWebRequest)WebRequest.Create(url);HttpWebResponseresult=(HttpWebResponse)req.GetResponse();StreamReceiveStream=result.GetResponseStream();Encodingencode=System.Text.Encoding.GetEncoding("GB2312");StreamReadersr=newStreamReader(ReceiveStream,encode);stringresultstring=sr.ReadToEnd();ReceiveStream.Close();sr.Close();首先用用户名和最后的维修单时间构造一个URL,然后通过HttpWebRequest类的Create方法打开这个URL,通过HttpWebResponse接收返回的数据,使用Stream读取返回流中的数据。最后的结果保存在resultstring变量中。按照设计的数据同步规则解析保存在resultstring变量中的记录和字段(代码略),然后把记录写入SQLServerCE数据库。/写入数据库cmd.CommandText="INSERTINTOJOB(id,jobname,jobdesc,jobtime,useraddress,userphone)" +"VALUES(<各字段数据>)"cmd.ExecuteNonQuery();使用SqlCeCommand类的ExecuteNonQuery方法执行不需要返回行记录的SQL语句。显示维修单列表在.NETCompactFramework中仍然支持数据绑定控件,因此我们在实现维修单列表时,采用DataGrid数据绑定列表控件。在窗口中创建DataGrid控件,命名为dataGridJobList,然后在属性窗口中单击TableStyles项的“”图标,将出现TableStyles集合编辑器,如图7所示:图7TableStyles集合编辑器在MappingName中输入“JOBLIST”,点击GridColumSytles旁边的“.”按钮,设定数据绑定的列映射。在设定列映射时,添加三列,映射名称分别是id,jobname,jobtime。如图8所示:图8列映射效果图在Form_load事件中添加数据绑定的代码:/数据绑定this.dataGridJobList.RowHeadersVisible=false;dataGridJobList.Font=newFont("宋体",9F,FontStyle.Regular);System.Data.DataSetdsJobList;System.Data.DataTabledtJobList;dsJobList=newDataSet();sql="selectid,jobname,jobtimefromjoborderbyjobtimedesc"SqlCeDataAdapteradapter=newSqlCeDataAdapter(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。通过上述操作就可以完成SQLServerCE数据与一个DataGrid控件的数据绑定。编辑并保存维修记录单当点击列表中的维修单时,将弹出维修记录编辑界面。在DataGrid的MouseUP事件中添加下列代码将可以获取当前点击的是哪一个维修单,并打开维修记录编辑界面。DataGridmyGrid=(DataGrid)sender;DataGrid.HitTestInfomyHitInfo=myGrid.HitTest(e.X,e.Y);if(myHitInfo.Type=DataGrid.HitTestType.Cell&&myHitInfo.Column=1) Cursor.Current=Cursors.WaitCursor; DataGridCellmyCell=dataGridJobList.CurrentCell; stringjobid=dtJobList.RowsmyCell.RowNumber0.ToString(); Cursor.Current=Cursors.Default; FrmJobfrmJob=newFrmJob(jobid); frmJob.ShowDialog();在FrmJob的Load事件中添加根据jobid查询维修单详细信息的代码,并将查询结果显示在界面上。stringsql="selectjobname,jobdesc,jobtime,userphone,useraddress,jobdonedescfromjobwhereid="+jobid;SqlCeCommandcmdDML=newSqlCeCommand(sql,conn);cmdDML.CommandType=CommandType.Text;SqlCeDataReaderdtr=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协议。结束语本文结合移动服务系统的开发过程介绍了SQLServerCE的特点以及安装、开发SQLServerCE应用程序的方法,如果需要更全面和详尽的了解SQLServerCE,可以参阅SQLServerCE附带的“BooksOnlie”。通过本文的介绍,大家可以看到利用ADO.NET开发SQLServerCE的应用程序,在开发方法上与在PC平台上使用ADO.NET非常类似,但总的说来还是要注意一下几点:SQLServerCE是用于移动设备上的一个很轻量级的数据库系统,其性能受移动设备的存储能力和计算能力的制约,因此在使用SQLServerCE时,尽量避免大数据量的操作,要尽可能的压缩SQLServerCE上数据的规模。SQLServerCE有一些比较特殊的地方需要注意,例如只能打开一个到SQLServerCE的连接,支持数据库口令和加密,支持部分函数等。在使用RDA或合并复制时,要结合自己的数据同步业务逻辑灵活运用,避免生搬硬套带来更多的不方便。注意使用SqlCeEngine类的Compact方法回收SQLServerCE数据库中浪费的空间。如果发现数据库文件已经达到几兆甚至将近十兆左右时,可以用Compact方法尝试压缩一下数据库。-