Chinaunix首页 | 论坛 | 博客
  • 博客访问: 416763
  • 博文数量: 152
  • 博客积分: 1885
  • 博客等级: 上尉
  • 技术积分: 1306
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-13 16:51
文章分类

全部博文(152)

文章存档

2013年(1)

2012年(17)

2011年(19)

2010年(109)

2009年(6)

我的朋友

分类: 数据库开发技术

2010-02-22 13:24:36

pb11+webservice开发分布式三层应用



一、   WEBSERVICE服务端的开发

1、         新建立一个workspace工作区

先择FILE菜单下的NEW,新建一个工作区。


点击后出现下图


在文件名处输入工作区的名称,假设我们的工作区名为webserver,单击保存按钮。这样工作区就建立成功了。

2、         建立一个.net web service 应用

点击FILE菜单下的NEW






选中 .net web service 点击 ok按钮


点击 next按钮


点击 next按钮


这里我们不修改pbl库名,当然你可以按你的意思修改库名,点击 next 按钮。



一直点 next按钮直到出现


这里需要注意一点,如果你当前的IIS端口,不是默认的80 ,那么在localhost后面要加上

“:
81”  ,假设你的端口号是81的话。

  再点击一次next直到finish按钮。





3、        连接数据库

我们先来建立一个数据库的连接以为后期的webservice服务提供一个连接。

打开系统生成的 n_webservice对像




在里面写上

// Profile EAS Demo DB V110

SQLCA.DBMS
= "ODBC"

SQLCA.AutoCommit
= False

SQLCA.DBParm
= "ConnectString='DSN=EAS Demo DB V110;UID=dba;PWD=sql'"

我是拷贝了,安装PB11默认的安装的ASA数据库,这里你可以修改成你的数据库连接参数。



数据库建立完成后,我们再建立一个ue_retrieve的方法用来提取数据库数据




1、  在N_webservice对像里创建立一个名为DS1的数据存储 datastore

2、  在DS1 的 dberror里面写上

ls_err_a
=sqlerrtext////////



注意:将ls_err_a  定义为一个实例变量,如果你看不清楚出入参定义可以将本图片另存放大就可以看到了。

////////////////////////////////////////////////////////////////////////////

//          用于取单一的数据窗口blob值                              //

//                                                                        //

//    将数据窗口检索到blob,并将blob返到客户端                            //

//                                                                        //

//    guoac                                                     //

//                                                                       // 

//    入参 ls_syntax--传入一个字符串的数据窗口对像语法用于重构数窗        //

//    入参 ls_sql   传入一个条件字符串,用于附加where 条件          //                                                  //

//    出参 dwo_blob 传出一个存储数据窗口对像的blob                        //

//                                                                        //

//    dwo_blob  回传参数                                                  //

////////////////////////////////////////////////////////////////////////////

long ll_row,ll_returnrow

string ls_returnmodiy

string ls_oldsql,ls_newsql,ls_error

string csa

int i,LI_WHERE





connect;



if SQLCA.SQLCode <> 0 then

       as_returnerr
="连接数据库出错,请检查数据库连接参数。"+string(sqlca.sqlerrtext)

      
return -1////创建数据窗口出错

end
if





if ds1.create(as_syntax,ls_error)<>1 then

       disconnect
using sqlca;

       as_returnerr
="服务端重建数据窗口出错! "+ls_error

      
return -1////创建数据窗口出错

end
if

int li_a

li_a
=ds1.settransobject(sqlca)

if li_a<>1 then

       disconnect
using sqlca;

       as_returnerr
="服务端设置数据存储事务出错!"

      
return -1///设置对像事物出错

end
if



ls_oldsql
=ds1.getsqlselect()



if trim(ls_oldsql)='' or isnull(trim(ls_oldsql)) then

       disconnect
using sqlca;

       as_returnerr
="传入的数据窗口对像sql语法为空!"

  
return -1 //取新窗口语法出错

end
if





LI_WHERE
= pos(UPPER(ls_oldsql),'WHERE',1)



IF LI_WHERE
= 0 THEN

        ls_oldsql
=ls_oldsql + " WHERE 1=1  "

END IF

ls_newsql
=ls_oldsql  +' '+as_sql 

if trim(ls_newsql)='' or isnull(trim(ls_newsql)) then

       disconnect
using sqlca;

       as_returnerr
="连结后的sql语法为空!请检查传入的数据窗口对像sql语法。"

  
return -1 //取新窗口语法出错

end
if



if Match ( ls_newsql, '"' ) then

       disconnect
using sqlca;

       as_returnerr
="重组后的sql语法出错,数据窗口语法不能包含双引号!"+ls_newsql

  
return -1//设置新窗口语法出错

elseif not  Match ( upper(ls_newsql),
"WHERE"  ) then

          disconnect
using sqlca;          

              as_returnerr
="重组后的sql语法出错,数据窗口必须包含一个where条件"+ls_newsql 

             
return -1//设置新窗口语法出错

end
if





if ds1.modify( '.Table.Select="' + ls_newsql+'"'  )<>"" then

       disconnect
using sqlca;

       as_returnerr
="重组后的sql语法出错,请检查数据窗口对像SQL语法。"+ls_newsql          

      
return -1//设置新窗口语法出错

end
if

ll_row
=ds1.retrieve()



if ll_row<0 or isnull(ll_row) then

   disconnect
using sqlca;

   as_returnerr
="数据检索出错!"+ls_err_a+ls_newsql

      
return -1//服务端检索数据出错

end
if



if ds1.modify('.Table.Select="' + ls_oldsql+'"'  )    <>"" then

       disconnect
using sqlca;

       as_returnerr
="还原旧数据窗口语法出错,请检查数据窗口对像语法是否含有双引号。"+ls_oldsql

      
return -1 //还原旧数据窗口语法出错

end
if



ll_returnrow
=ds1.getfullstate(dwo_blob)

if ll_returnrow<0 or isnull(ll_returnrow) then

              disconnect
using sqlca;

              as_returnerr
="服务端进行blob时,获取数据行出错!"

         
return -1 //封装到blob变量时出错

end
if

      

       disconnect
using sqlca;

       destroy ds1;

       as_returnerr
="数据检索成功!"

//     destroy  n_webservice

      
return ll_returnrow

  

3、  把服务端发布到IIS服务

打开我们的P_webservice_webservice编译object 。点击编译,pb11会自动将webservice发布到我们原来定义的IIS服务器上

发布的时候要注意一点就是在objects选项卡上,必须先中我们上面的函数(或者叫方法),library list选项卡上要选上我们的pbl库文件。点击第一辆小车 deploy project其它就交给pb自已去完成了。

4、  编译完成后run一下我们的webservice看看是否发布成功,


出现上图并能看到我们定义的函数(我总是喜欢叫它们方法),webservice就算是发布成功了。



这样我们就完成了一个服务端检索方法。下一节我们接着继续讲解如何用客户端检索数据。





二、          客户端调用webservice

1、  建立一个PB应用


点击确定后


点击 finish 完成

2、  给工程附加 pbsoapclient110.pbd

这个文件通常在pb11的安装目录里,可以通过搜索找到它,然后将这个文件拷贝到我们新建应用的目录下,并附加到工程里面来。


3、  为应用添加一个webservice proxy



函数添加完成后在工程里面添加一个窗口,我们来实验一下我们前面的工作

注意:应用程序要与webservice通讯都要通过webservice proxy来完成,所以我们首先要建立一个 proxy




Ok后




这里的 file name

如果你记不住就打开webservice 端,工程文件的 object项上面去找



然后一直下一步到下图


写上一个proxyname  我写的是  myproxy

一直到下一步完成。




打开我们刚才定义的代理,并编译,顺利的话会看到库文件中添加了很多结构,这些我们都不用管,接着做我们后面的工作就好。



4、  新建一个custom class


5、  给新建立的对像添加一个函数


这个函数就是代替二层开发模式下的retrieve函数的,这里你可以将这个函数多次重载以方便前台开发人员调用,目前这个函数支持 给窗口添加where条件,检索并返回错误或成功的信息。以及返回检索到的行数。还是不太明白的可以加我的QQ:
47570471,我的文笔从上幼儿园开始就不是强项,估计说得也不是太明白,不过欢迎大家QQ骚扰。总之就是重载到前端开发人员分不出是在开发二层还是三层就算ok了,见下图:


为对像添加二个实例变量

SoapConnection i_conn

myproxyn_webservicesoap pb_soap
//// myproxyn_webservicesoap这个名称如果你前面建立代理的时候用的是myproxy那应该就是这个,如果不是就去找你生成的代理对像名称。

Constructor 事件里面写上

i_conn
=create SoapConnection

//i_conn.setsoaplogfile( "mis.log")

i_conn.createinstance( pb_soap,
"myproxyn_webservicesoap")



destructor事件里面写上

destroy pb_soap;

destroy i_conn;

对像到这里建立完成。

1、  给应用添加一个全局变量

soapserver mis

注意:soapserver为上面定义的对像的名称。

在窗口的open事件里面上

mis
=create soapserver

2、  做一个数据窗口(这个不用说了吧)

3、  把数据窗口拖到我们的测试窗体

4、  拖一个commandbutton

里面写上: mis.retrieve(dw_1)
//////

如果数据检索到数据窗口了,那么我们本次的实验就算成功了。



下一节我们接着讲单数据窗口及多数据窗口的 update

以及存储过程的调用及oracle序列的通用方法………

Guoac  qq:
47570471





三、          三层结构的更新

1、  webservice端方法

新建立一个函数


int li_change=0

string ls_error=""

connect;



if SQLCA.SQLCode <> 0 then

       as_err_return
="连接数据库出错,请检查数据库连接参数。"

      
return -1////创建数据窗口出错

end
if







if ds1.create(as_syntax,ls_error)<>1 then

        disconnect
using sqlca;

        as_err_return
="服务端重建数据窗口出错,请检查您传入的数据窗口对像!"+ls_error

      
return -1

end
if

if ds1.settransobject(sqlca)<>1 then

        disconnect
using sqlca;

        as_err_return
="服务端设置数据存储事务出错!"+ls_err_a

       
return -1

end
if

li_change
=ds1.SetChanges(dwo_object)

if li_change = 1  then 

                    
if ds1.Update()= 1 then                      

                             commit
using sqlca;

                             disconnect
using sqlca;

                             as_err_return
="数据更新成功!"

                           
return 1

                    
else 

          as_err_return
=ls_err_a

                            rollback
using sqlca;

                            disconnect
using sqlca;                      

                           
return -1

                     end
if

else

        disconnect
using sqlca;

        as_err_return
=     "取更新行封装到blob时出错!"

      
return -1

end
if







2、  前端更新方法

建立的方法见前面,RETRIEVE的方法,这里我们建立一个update函数






int li_return,li_dwreturn

long ll_rv

string ls_syntax

blob lblb_data

       as_dwoname.accepttext( )

       li_dwreturn
=as_dwoname.GetChanges(lblb_data)

      
if  li_dwreturn=0   then

       as_err_return
='客户端数据窗口没有需要更新的数据。'

             
return  1

       end
if

  
if  li_dwreturn =-1 then

              as_err_return
="客户端取数据窗口变更封装到blob时出错。"

             
return -1

       end
if

ls_syntax
=as_dwoname.describe('datawindow.syntax')

if ls_syntax='' or ls_syntax="" then

       as_err_return
="客户端数据窗口语法为空。"

             
return -1

end
if

if MIS.uf_update(lblb_data,ls_syntax,as_err_return)=1 then

  as_dwoname.ResetUpdate()

 
return  1

else

 
return -1

end
if



近期因为项目的原因,可能没什么时候来整理这个文档了,只能先写到这里,如果有什么问题可以给我留言。另外关于多数窗的更新问题,我希望大家也能自已动手去试一下,方法就是传入一个数据窗口数组到WEBSERVICE,WEBSERVICE端进行多表多更的事务控制。



PB11
+WEBSERVICE+WINFROM应用方式是我们目前一个大型系统的开发模式。这样模式只需要发布WINFROM到IIS后,客户端就不需要安装任何技撑的东西,对于以后版本的的更新也由PB全自动管理。让PB的开发模式发生了很大的改变。另正式应用过程中还会涉及到应用服务器集群及数据库连接池的问题,不然每一次检索或更新都要连接数据库,可能谁都认为这不是个好的解决方案。更多需要优化及相关的领域的有待大家去研究。也希望有更多的人回到PB的开发阵营,呵,最起码招人的选择更多一些!开个玩笑。



另外在项目中可能还会有比如二层模式下通用查询,子数据窗口检索,存储过程通用方法等一些问题。希望有更多的人来研究这些东西。呵,孤军混战确实不是好的主意。

 

回答者:lzp_lrp - 2009-09-24 12:12:58
pb11 开发 web service的电子书

按照步骤做即可


阅读(1683) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~