VB中远程数据库的访问(1)-数据连接

 

在VB中,用microsoftjet数据库引擎和数据访问对象DAO(dataaccessobject)可以创建功能强大的客户/服务器应用程序。对远程数据库的访问是开发这类应用程序的关键环节,本文将介绍在VB中用DAO通过miscrosoftjet数据库引擎访问远程数据库的方法。

  用DAO访问远程数据库大体上可以通过三步来实现,即数据连接、数据处理和断开连接。下面主要介绍数据连接和数据处理的具体操作。

一、数据连接

  DAO一般通过链接远程表的方式来进行数据连接。这样,数据虽然驻留在远程数据源上,但在本地的microsoftjet数据库中可以存储与远程数据的永久性连接,同时缓存链接的表结构信息,从而在下一次访问该表时,不用再次从服务器中检索这些结构信息,加快了连接速度。一旦链接了一个表,该链接便会保留在各会话期间,直到连接断开。链接远程表的具体操作是:

用opendatabase方法打开将要包含该链接的本地microsoftjet数据库

用createtabledef方法在该数据库中创建一个新的tabledef对象

将tabledef对象的connect属性设置为一个合法的连接字符串,标识要访问的远程数据库类型、数据文件的路径以及用户名和远程数据源密码等。

将tabledef对象的sourcetablename属性设置为远程数据库中要访问的表的名称。

添加tabledef对象到tabledefs集合中。

实现链接远程表操作的过程如下:

publicsublinktable(strdbasstring,strrodbasstring,strcnasstring,strtdfasstring,_linktdfnameasstring)
dimlinktdfasnewtabledef
setdbs=opendatabase(strdb)
linktdf.name=linktdfname
100
temptable=ucase(linktdf.name)
fori=0todbs.tabledefs.count-1
ifucase(dbs.tabledefs(i).name)=temptablethen
ifmsgbox(linktdfname "已存在,是否删除?",_
vbquestion vbyesno)=vbyesthen
dbs.tabledefs.deletelinktdf.name
exitfor
else:msgbox"重新输入新表名"
linktdfname=inputbox("新表名")
goto100
endif
endif
nexti
setlinktdf=dbs.createtabledef(linktdfname)'链接远程表
linktdf.connect=";database=" strcn
linktdf.sourcetablename=strtdf
dbs.tabledefs.appendlinktdf
endsub

上述过程用来实现远程表的连接,它有5个参数,其中strrodb是要访问的远程数据库名(包括路径);strtdf是该数据库中的表名;strdb是要链接的本地数据库(包括路径);linktdfname是本地数据库的一个新表名,用来建立远程表的链接;strcn是指定连接信息的字符串。需要特别注意的是,除了在访问远程microsoftjet数据库时,连接字符串要以分号(;)开头外,指定连接信息的字符串都必须以所访问的远程数据库类型开头。DAO可以访问的远程数据源有以下三类:

.microsoftjet数据源,如:access数据。

.iisam(可安装的索引化顺序访问方法)格式数据源,如:foxpro、paradox、dbase数据。

.odbc数据源,如:sqlserver数据、oracle数据。

  例如:设网络服务器名为server,共享目录为c:/sales的foxpro3.0数据库,连接字符串应为

strcn="foxpro3.0;database=//server/c$/sales/region1"

  此外,DAO通过microsoftjet数据库引擎访问远程数据时,还可以用opendatabase方法直接打开远程表。在本地数据库中并未存储与远程数据源建立连接所需要的信息。如果使用链接方式访问数据,则不必在每次会话开始时提供连接信息,从而可以提高效率。->

 

 

VB中远程数据库的访问(2)-数据处理

 

二、数据处理

  数据连接建立后,可以用openrecordset方法打开一个记录集,并可用dbgrid控件和data控件方便地浏览整个记录集。如果使用表类型(table-type)记录对象,则对应的是一个实际存在的数据库表,在多用户环境下,其它用户对数据的修改会立即反映到表中;如果使用动态集类型(dynaset-type)记录对象,则对应的既可以是一个表中全部记录,又可以是一个查询的结果,并且可以更新记录集中的记录;如果使用快照类型(snapshot-type)记录对象,则对应的可以是表中的全部记录,也可以是一个查询结果,但不能进行记录的增加、删除和修改操作。此外,还可以建立其它类型的记录对象,如仅向前型(forwardonly-type)记录对象和动态型(dynamic-type)记录对象。

下面是打开动态集记录对象并显示记录的过程:

publicsubrst_display(strdbasstring,strrstasstring,strformasform)
setdbs=opendatabase(strdb)
setrst=dbs.openrecordset(strrst,dbopendynaset)
strform!data1.databasename=dbs.name
strform!data1.recordsource=rst.name
strform!data1.refresh
strform!dbgrid1.rebind
endsub

  上述过程有三个参数,其中strdb用来指定本地数据库名(包括路径),linktdfname是在本地数据库中新建的链接远程表的表名,strform是网格控件和数据控件所在的窗体名。调用此过程可以基于新表建立一个动态集类型的记录对象,并可在网格中浏览各个记录。

  断开连接可以通过关闭应用程序或设置连接超时来实现。注意:如果对数据库对象使用close方法,则由于在miscrosoftjet数据库引擎内部缓存了连接,实际上连接并未取消。->

 

 

VB中远程数据库的访问(3)-应用举例

 

三、应用举例

  以上介绍了用dao访问远程数据库的具体操作,下面通过一个例子说明链接远程表和建立记录集对象的方法。

  首先建立一个新工程,在窗体上画5个命令按钮,1个数据控件和1个数据网格控件(dbgrid)。各对象的属性设置见表1。

表1窗体1对象属性设置

对 象

标 题(caption)

名 称(name)

窗体

远程数据访问

form1

命令按钮1

链接远程表

cmd 链接

命令按钮2

添加

cmdadd

命令按钮3

删除

cmddel

命令按钮4

修改

cmdmodify

命令按钮5

结束

cmdend

数据控件

data1

data1

数据网格

dbgrid1

 

其中dbgrid1中的datasource属性设为data1,命令按钮2,3,4的visible属性设为false。

三、应用举例

编写如下事件过程:

privatesubcmdadd_click()'添加记录子过程
onerrorgotoerrhandler
withrst
.addnew
fori=0to.fields.count-1'遍历记录集中的每个字段
'在输入框中输入各字段的数据
.fields(i).value=inputbox
("输入记录信息"&vbcr "字段名:" .fields(i).name)
nexti
.update
endwith
data1.refresh
dbgrid1.rebind
errhandler:'错误处理
selectcaseerr
case3022,3421
msgbox(error vbcr "输入无效")
exitsub
caseelse
response=0
exitsub
endselect
endsub
privatesubcmddel_click()'删除记录过程
onerrorgotoerrhandler
begintrans'事务处理
withdata1.recordset
if.bofand.eofthenexitsub
'如果没有记录,退出过程
.delete'删除
if.bofand.eofthen
'如果没有记录,退出过程
exitsub
elseif.eofthen.movelast
'如果删除的是最后一条记录,光标移至最后一记录
else:.movenext
'移至下一条记录
endif
endwith
ifmsgbox("确实要删除这一记录?",
vbquestion vbyesno)=vbyesthen
committrans'确认
data1.refresh
else
rollback'撤消改动
data1.refresh
endif
errhandler:'错误处理
selectcaseerr
case3021'无当前记录
msgbox("无当前记录,请选择要删除的记录")
exitsub
caseelse
msgbox(error)
exitsub
endselect
endsub
privatesubcmdend_click()
end'结束应用程序
endsub
privatesubcmdmodify_click()
dbgrid1.allowupdate=true'允许修改
endsub
privatevsubcmdlink_click()
form1.hide
form2.show
endsub
privatesubdbgrid1_aftercolupdate(byvalcolindexasinteger)

'数据修改后触发该事件

onerrorgotoerr1
data1.refresh
err1:
selectcaseerr
case0
response=0
caseelse
exitsub
endselect
endsub
privatesubdbgrid1_beforecolupdate
(byvalcolindexasinteger,oldvalueasvariant,cancelasinteger)

'数据修改前触发该事件

onerrorgotoerrhandler:
begintrans
ifmsgbox("确实要修改这一内容?",vbquestion vbyesno)=vbyesthen
committrans
else
rollback
data1.refresh
endif
errhandler:
selectcaseerr
case0
response=0
caseelse
msgbox(error)
exitsub
endselect
endsub
privatesubform_load()

'在窗体装入时,网格中的数据不可添加,修改

dbgrid1.allowaddnew=false
dbgrid1.allowupdate=false
endsub
privatesubform_resize()
onerrorresumenext
'当窗体调整时会调整网格
dbgrid1.height=me.scaleheight-data1.height-cmddel.height-30
endsub

在工程中添加一个窗体,在窗体上画6个标签,1个命令按钮(标题为“确认”,名称为cmd确认),3个文本框和1个组合框。

在窗体的声明部份输入以下代码:

'声明窗体层变量
dimrodbsasdatabase
dimstrdbasstring,strrodbasstring,strcnasstring,strtdfasstring
dimlinktdfnameasstring
编写如下事件过程:
privatesubcmdOK_click()
onerrorgotoerrhandler:
strdb=text2.text
'本地数据库名及路径
linktdfname=text3.text
'本地数据库中新建的链接远程表的表名
strcn=strrodb'连接字符串
strtdf=combo1.text'指定远程数据库中要访问的表
'调用linktable过程
calllinktable(strdb,strrodb,strcn,strtdf,linktdfname)
'调用rst_display过程
callrst_display(strdb,linktdfname,form1)
form2.hide
form1.show
form1.caption="远程数据:" strcn "-" strtdf
'显示“添加”,“删除”,“修改”控件
form1.cmdadd.visible=true
form1.cmddel.visible=true
form1.cmdmodify.visible=true
errhandler:
selectcaseerr
case0
response=0
caseelse
msgbox(error vbr "重新输入")
exitsub
endselect
endsub
privatesubcombo1_gotfocus()
strrodb=text1.text'指定远程数据库名及路径
setrodbs=opendatabase(strrodb)'打开远程数据库
'删除combo1中的内容
ifcombo1.listcount>=1then
fori=combo1.listcount-1to0step-1
combo1.removeitemi
nexti
endif
'把数据库中的表名加到combo1中
fori=0torodbs.tabledefs.count-1
combo1.additemrodbs.tabledefs(i).name
nexti
endsub
->