Tag: Delphi .net WebService 最近公司有个系统升级,老系统为delphi所编写;老系统为传统的C/S两层结构,有一个瓶颈就是我们的客户端经常需要从数据库刷新数据 ,而且这些数据都是一样的,这极大地影响了系统效率,在系统升级时我们考虑使用WebService解决这一瓶颈;初步想法是需要刷新数据时由 WebService中间层去数据库提取数据,所有的客户端都到中间层拿刷新后的数据,这样就避免了所有的客户端都直接去操作数据库提取同样的 数据。但是用什么平台实现WebService中间层呢?根据公司的技术特点,那么我们初步定为考虑.net和delphi自己做中间层。 用.net作为中间层实现,优势很明显: 1.微软已经把WebService框架搭建好,开发非常简单; 2.我们的服务器为微软平台,使用微软的.net技术应当能够提供很好的效率; 3..net平台提供了现成的全局Session对象,很容易实现我们的需求。 劣势为: 1. 系统采用两套开发平台,接口不统一;比如说.net的数据集DataSet在delphi里怎么用? 2. 两套开发平台增加程序员学习难度和维护难度; 使用delphi作为中间层实现,我们预想好处为: 1. 中间层和客户端都为delphi实现,提供较好的兼容性,可能可以直接传递数据集; 2. 统一的开发平台,易于学习和维护; 劣势为: 1. 我们使用的Delphi版本为6.0,显然它不是作为分布式开发的主流平台; 2. 如何控制全局数据集估计没有.net方便; 3. 效率不可预见; 我查阅了很多文章,有如下结论: 1. Delphi作为中间层实现的话,除了能够传递简单类型以外;负载类型只能支持继承自TRemoteTable的子孙类,以及这些子孙类组成的动态 数组;这样我所预想的直接传递数据集的想法落空;只能在中间层得到数据集后,变为动态数组传递到客户端,客户端解析后还原为数据集, 效率太低; 2. .net平台DataSet可以化为xml数据流传递为delphi客户端,delphi客户端可以根据事先定义好的解析文件,将此xml数据流装载到 TClientDataSet中; 就这两点就足以使我选择了.net作为中间层实现; 其中的技术关键点就是中间层的DataSet和Delphi的ClientDataSet的转换,下面给出具体实现方法: .net端的示例代码如下: DataSet ds = SqlHelper.ExecuteDataset(conStr,CommandType.Text,sqlText);//得到DataSet System.Text.StringBuilder strbuilder=new System.Text.StringBuilder(); System.IO.StringWriter writer=new System.IO.StringWriter(strbuilder); ds.WriteXml(writer,System.Data.XmlWriteMode.IgnoreSchema);//将DataSet转换为xml数据流,忽略一些dataset特有的动作结构等 return strbuilder.ToString(); 客户端收到的数据流入下所示:
<车辆编码>
00001
<实际标识>
adah
<工作状态>
8
<所属分站编码>
001
<插入时间>
2005-08-23T10:15:28.6170000+08:00
<车辆编码>
00002
<实际标识>
b
<工作状态>
7
<所属分站编码>
002
<插入时间>
2005-08-23T11:11:56.7570000+08:00
<车辆编码>
00003
<实际标识>
c
<工作状态>
64
<所属分站编码>
003
<插入时间>
2005-08-23T11:15:52.3070000+08:00
注意,我们需要给这个xml文件流添加第一行
。 将这个xml文件流保存到文件data.xml中;用自带的工具XmlMapper打开data.xml,生成transfromation结构,保存到Todp.xtr文件中; Delphi端演示代码 var xmlStr: string; st: TSTringStream; XMLDoc:IXMLDocument; begin xmlStr:= GetService1Soap.GetAmbulance; xmlStr:= '
' + #10 + xmlStr; st:= TStringStream.Create(xmlStr); ClientDataset1.Active := FALSE; //SOAPResponse.Position := 0; XMLDoc := NewXMLDocument; XMLDoc.Encoding := 'GB2312'; //SOAPResponse.Position := 0; XMLDoc.LoadFromStream(st); XMLTransformProvider1.TransformRead.SourceXmlDocument := XMLDoc.GetDOMDocument; ClientDataset1.Active := TRUE; 其中XMLTransformProvider1的TransformRead的TransformationFile属性选择我们生成的Todp.xtr,ClientDataSet1的Providor属性选择 XMLTransformProvider1;这样就将数据倒入道ClientDataSet中。