浅谈VFP使用SPT技术开发C/S应用系统
2017-06-08陈兰贞陈玉祥
陈兰贞 陈玉祥
前言
Visual FoxPro数据库开发工具(以下简称 VFP)具有易于掌握、易于开发、项目管理方便灵活、拥有强大编程语言、对系统资源要求不高等特性。长期以来,VFP以其小而巧的特点,受到中、小型数据库开发者的青睐。随着VFP程序应用的深入,我们会发现VFP数据库文件(.dbc)、表文件(.dbf)存在一些弊端,因为这些固有的问题,开发人员不得不去寻求更安全的开发策略,保证我们的应用程序,稳定可靠,安全无患。通常的解决办法是使用结构化查询语言服务器SQL Server,提供后台数据服务。
一、做在前面
1.在设计VFP表单时,改善对DBF表的访问:
通常,FoxPro应用程序都使用DBF表来存储数据。对于单用户的应用DBF表是很有效的。可以独占的打开表并绑定表的字段到表单控件(如文本框和复选框)。可以不再使用内存变量来复制数据字段以用于增加或编辑。可以简单的把缓冲模式设为3(开放式行缓冲)以有效地把表单与数据字段分离开来,然后发出TableUpdate(.T.)以永久地修改数据,或者发出TableRevert(.T.)以忽略所发生的改变。
对于多用户的应用,只需要以共享方式(SHARED)打开所有的DBF表。
通常,在表单的数据环境里我们会加入所有的表和视图以便其自动打开。由于在表单控件创建前所有别名已经打开(具体的说表单对象在表单的Load和Init事件间生成),使用表单数据环境可以节省我们的开发时间。当把一个表加入表单的数据环境里,当表打开时,表的记录指针将会移动指向当前索引标识的第一个记录。
但是使用数据环境,在多用户环境下,要有效控制数据表,却不是很顺利,可能会有很多“表已打开的”的提示。
所以,要开发多用户应用系统,我们经常用自己的代码,在表单的Load事件里打开光标和表。这样,我们可以控制得更多。而这种控制,将会让我们在以后面对更多用户时,不再措手不及。
2.建立数据字典
在表单的Load事件里,以上面调用OpenDBF过程的方式来创建每一个光标,这是一种很好的方法。但是这种方法还是存在一定的隐患,虽然这种几率是非常的小。OpenDBF.PRG打开的是物理存在的表,万一该表被误删了或损坏了,这么办?相信每位程序员都会有自己的应对策略。我的方法是建一个所有临时表的备份,当打开表不成功时,用备份覆盖一下。
有一种更好的方法:可以建立一个包含所有需要创建的光标的信息的数据字典,然后调用下面讲述的CreatCursor()函数。用这种方法,虽然前期工作要多一点,但是临时表现场建立,那“表不存在”,“不是一个表”等错误提示,想出来也没人去叫它了。
二、建立SPT连接
为了使用SPT,程序必须建立一个服务器连接。通常使用SQLConnect()函数或SQLStringConnect()函数来建立该连接。
1.方式一:使用SQLConnect()函数建立SPT连接
SQLConnect()使用DSN,使用“控制面板”中的“ODBC数据源管理器”创建某个数据库的ODBC 数据资源名,即DSN,这样以后可以通过使用数据库DSN连接具体的数据库。
“ODBC数据源管理器”提供了三种DSN,分别为用户DSN、系统DSN和文件DSN。其中,用户DSN会把相应的配置信息保存在Windows的注册表中,但是只允许创建该DSN的登录用户使用。系统DSN同样将有关的配置信息保存在系统注册表中,但是与用户DSN不同的是系统DSN允许所有登录服务器的用户使用。
与上述两种数据库DSN不同,文件DSN把具体的配置信息保存在硬盘上的某个具体文件中。文件DSN允许所有登录服务器的用户使用,而且即使在没有任何用户登录的情况下,也可以提供对数据库DSN的访问支持。此外,因为文件DSN被保存在硬盘文件里,所以可以方便地复制到其它机器中。这样,用户可以不对系统注册表进行任何改动就可直接使用在其它机器上创建的DSN。
在以上三种数据库DSN中,建议大家选择系统DSN或文件DSN,如果更喜欢文件DSN的可移植性,可以通过在NT系统下设定文件的访问权限获得较高的安全保障。
2.方式二: 使用连接串SQLStringConnect()函数建立SPT连接
StrCmd=[Server=(local);Driver={SQL Server};Database=One;UserID=sa;pwd=sa;]
Handle = SQLStringConnect ( strCmd )
lr= SQLExec ( Handle, [SELECT * FROM CUSTOMER], [AllCusts] )
這将返回整个customer表给命名为“AllCusts”的光标。
3.上面两种方法之一取回需要的数据后,用SQLDisconnect(句柄) 语句来关闭连接
SQLDisconnect( lh )
三、从SQL Server返回数据到本地光标
可是,上面返回的光标并不是我们绑定于表单控件的光标,因为SQLExec()总是创建一个新的光标,我们不能使用已经存在的光标作为SQLExec()的第三个参数。当我们在设计表单时,经常从表单数据环境的表里拖出字段到屏幕上,于是自动设置该表的这个字段为该控件的绑定数据源(ControlSource)。
该如何在不断开绑定的情况把这两者连接起来?鉴于我们的经验,可以使用了一个简单的解决办法,仅以较小的性能损失用以免除大量的编程。在表单的Load事件里,我们已按“做在前面”所说,创建好了我们需要的光标,并把表单控件梆定于它。然后,当我们用SPT从SQL Server返回数据给SQL光标时,只需要简单地ZAP本地光标并把返回的SQL光标数据追加进来,或者直接把返回的SQL光标数据追加到Load事件里打开的光标,那么它不会断开表单上各控件的数据绑定。
需要注意的是返回光标字段名与Load事件里打开的光标的字段名应该是相同的。
四、将新增、修改、删除记录写回到SQL?Server数据库
前面讲过SQL Server是一个简单的机制,常用的就是4条命令:Insert、Select、Update、Delete。
那么我们怎么用SPT将我们的数据变化写回到SQL Server数据库?
我们可以构造Insert、Update、Delete语句来发送数据到SQL Server。Update、Delete语句必须包含一个或多个关键字段以唯一地标识需要更新或删除的记录。沿用前面建立SPT连接的句柄Handle:
1.新增数据
StrCmd_1 = [INSERT INTO authors (au_id, au_lname, au_fname, phone, address,;
city,state,zip,contract) VALUES ('999-99-9999', 'White', 'Johnson', )
StrCmd_2 = ['408 496-7223','Bigge Rd', 'Menlo Park', 'CA','31002', '1')]
lr = SQLExec ( Handle, StrCmd_1+ StrCmd_2)
IF lr<0
Msg = [新增数据失败!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
值得注意的是:这里要遵守对该表数据的约束,要不然,总会以失败告终。
2.修改数据
StrCmd = [UPDATE authors SET phone = '999 496-7223', address = '2036 shiqiaoyjl' ;
WHERE (au_id = '999-99-9999') AND (au_lname = 'White')]
lr = SQLExec ( Handle, StrCmd )
IF lr<0
Msg = [修改数据失败!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
3.删除数据
StrCmd = [delete authors WHERE (au_id = '999-99-9999') AND (au_lname = 'White')]
lr = SQLExec ( Handle, StrCmd )
IF lr<0
Msg = [删除数据失败!]
MESSAGEBOX( Msg, 64, _VFP.Caption )
ENDIF
五、经验之谈
1.用SPT方式可以很好的使用事物处理
也许我们记忆忧新,在使用DBF表时,是用开放式行缓冲方式,然后发出TableUpdate(.T.)以永久地修改数据,或者发出TableRevert(.T.)来忽略数据更改的。还有在用远程视图方式整合SQL Server开发时,用的也是缓冲的机制。这种机制犹如黑匣子,我们控制不了其操作过程。用SPT方式就不一样,用这种方式,我们可以想回滚到哪里就回滚到哪里。
2.保留选项表的本地备份
可以复制部分SQLSerever表为DBF表到本地应用程序目录。你也许会感到奇怪,我用了SQLSerever表,為什么还要用DBF表?原因很简单,是因为性能。DBF表小而巧的特性,对数据量少,单用户独占使用的环境下有其无可比拟的性能优势。
我们的很多表单会有组合框或者列表框,这些组合框和列表框显示的数据源大多来自小的数据表,而且这些数据不是经常改变的。那就没必要在每次实例化表单时为每一个小表都连接到SQLServer。取而代之的是,可以以DBF表的方式为这些表在本地保留完整的备份,只在服务器表数据改变时再刷新它。
参考文献
[1]《在VFP里操作和管理SQL?SERVER(介绍SQL-DMO) 》,作者:buffer,下载地址:http://www.myf1.net/bbs/dispbbs.asp boardID=1&replyID=189716
&ID=180379&skin=1
[2]《FoxPro开发者学SQL》,作者:娄山关.下载地址:http://www.myf1.net/bbs/dispbbs.asp?boardID=1&replyID=217870&ID=238414&skin=1
[3]《SQL SERVER 起步》,作者:陈纯.下载地址:http://www.vfp.cn/article_
view.asp id=493