Visual FoxPro 9 CSODBC方面极富人性化的增强.docx
- 文档编号:7381760
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:8
- 大小:21.91KB
Visual FoxPro 9 CSODBC方面极富人性化的增强.docx
《Visual FoxPro 9 CSODBC方面极富人性化的增强.docx》由会员分享,可在线阅读,更多相关《Visual FoxPro 9 CSODBC方面极富人性化的增强.docx(8页珍藏版)》请在冰豆网上搜索。
VisualFoxPro9CSODBC方面极富人性化的增强
VisualFoxPro9CS(ODBC)方面极富人性化的增强
VisualFoxPro9C/S(ODBC)方面极富人性化的增强
作者:
mihu
2004年6月,微软公司如期发布了全球Foxer翘首期盼代号为Europa的VisualFoxPro9beta版(以下简称VFP9),下文是我学习、探索VFP9C/S方面新增功能时的一些心得,供大家一起分享。
自从VFP8开始,在C/S方面提供了一个CursorAdapter类,CursorAdapter是一个基于松散耦合思想设计的对象化的Cursor处理模型。
对CursorAdapter类很多人对其褒贬不一,特别是一些老的Foxer认为做C/S系统用SPT就足够了,何必再增加一个类呢?
但我可以这么说,从VFP9开始,几个CursorAdapter新增加的功能,相信足以使那些纯使用SPT的Foxer心动不已了。
下面我先谈谈VFP9在CursorAdapter部分的几个增加和增强。
1.属性值可以超过255个字符
大家都知道,VFP的表单、类库和报表等其实都是以DBF形式存放,VFP9以前属性是以(C)字符型存放,VFP9中做了修改,以(M)备注型存放,这样使得在VFP9开始,属性值突破了255个字符的限制。
用过CursorAdapter类的人都知道,VFP8时其几个属性SelectCmd、CursorSchema、UpdateNameList、UpdatableFieldList的长度不能超过255个字符,这在VFP8时让人感觉是一件非常滑稽和痛苦的事情,当后台表的字段数一多,连使用它自身生成器生成的字符串都要报错,不能保存,这点造成CursorAdapter使用起来极为不便,使得CursorAdpter的生成器变成了摆设,也是全球Foxer要求解决的呼声最多的地方,现在这个问题在VFP9中终于得到了彻底解决。
2.NoData和UseCursorSchema属性
VFP8时当把CursorAdapter设计时放到表单的数据环境里,使用CursorFill()里的这两个参数极为不便,尤其是对初学者,现在好了,把这两个属性单独列了出来。
3.TimeStamp时间戳字段
VFP8的CursorAdapter虽然WhereType可以等于4,可是其实时间戳字段真正在更新时却过滤掉了,因为你前台是不更改这个字段的,所以CursorAadpter,更新后台时是不会自动把这个时间戳字段加进更新语句,所以根本不起任何作用。
现在VFP9的CursorAdapter增加了TimestampFieldList属性,如果你的后台表里有时间戳的话,只要设置一下这个属性,然后设置WhereType=4即可,注意,UpdateNameList和UpdatableFieldList里还是要把时间戳字段加进列表,呵呵个人感觉,微软工程师在偷懒,其实这个只要判断一下就可以了,何必还要加进UpdateNameList和UpdatableFieldList,期待VFP9SP1能加以改进。
4.RecordRefresh()
VFP8时CursorAdapter只能用CursorRefresh()来刷新前台,可很多时候,我们可能只需要刷新其中一条或者几条记录的数据,可CursorRefresh(),如果前台记录有1000条,也要全部重新读一遍,读取完毕以后,记录指针却始终定位在第一条记录,这样既巨大的浪费了网络资源,同时很多情况下还要花费很大的精力重新定位记录指针。
现在VFP9增加了这个极富人性化的方法-----RecordRefresh(),能做到任意刷新此Cursor里的任意一条或者连续几条记录,而且当前记录指针保持不变,看到这里相信做过C/S程序的朋友们是不是有一种跃跃欲试的感觉?
这个可以期盼已久的功能啊。
RecordRefresh()里有2个参数,RecordRefresh(nRecords,nRecordOffset)
1)nRecords表示要刷新几条记录
2)nRecordOffset记录偏移量,指是当前记录开始加几条记录
例子1,比如当前记录号是第5条,我要刷新第7、8两条记录,
oCa.RecordRefresh(2,-2)
例子2,只刷新当前记录,
oCa.RecordRefresh
(1)
5.CursorAdapter的Auto-Refresh
VFP9提供了记录的Auto-Refresh,其作用、功能、效果和前面介绍的RecordRefresh()基本相似,有异曲同功之妙用。
让我们来看看具体是怎么使用的吧:
InsertCmdRefreshFieldList、InsertCmdRefreshKeyFieldList、InsertCmdRefreshCmd
这三个新增的属性是针对新增记录时使用,一般我们只需要设置InsertCmdRefreshFieldList、InsertCmdRefreshKeyFieldList即可,从字面已经非常好理解需要设置的内容,InsertCmdRefreshKeyFieldList如果和CursorAdapter的KeyFieldList相同,可以不设置,一般情况下都是相同的。
UpdateCmdRefreshFieldList、UpdateCmdRefreshKeyFieldList、UpdateCmdRefreshCmd
这三个新增的属性是针对修改记录时使用的,一般我们也只需设置UpdateCmdRefreshFieldList和UpdateCmdRefreshKeyFieldList即可。
UpdateCmdRefreshKeyFieldList如果和CursorAdapter的KeyFieldList相同,也可以不设置。
让我们设置好这些属性以后看看效果吧,当TableUpdate()提交后台成功以后,记录就自动刷新了,而且当前的记录指针保持不变,这难道不正是我们想要的吗?
请注意,RecordRefresh()和Auto-Refresh的区别,虽然RecordRefresh()也能刷新多条指定的记录,可只能是连续的几条记录,而Auto-Refresh却只刷新已修改过的记录。
RecordRefresh()刷新的记录可以自己来指定,可Auto-Refresh刷新的记录却是CursorAdapter来控制的。
使用RecordRefrsh()和Auto-Refresh功能时有点需要特别注意:
大家读到这里应该可以看出,其实此三项功能,都是依靠关键字来定位记录的,可当我们用自增量型字段做关键字时,当新增记录时,其值是更新成功以后才能得到,所以当在前台使用RecordRefrsh()和Auto-Refresh时会因无法定位记录而要出错或得不到正确结果。
所以当使用自增量型字段做关键字时要特殊处理一下,就是要另外设置一下InsertCmdRefreshCmd,通过InsertCmdRefreshCmd来取得刚生成的自增量值,这样就可以正常使用CusorAdapter的AutoRefrsh行级刷新功能了。
6.DelayedMemoFetch()
VFP8的CursorAdapter里有一个属性:
FetchMemo,当设置FetchMemo=.F.时,本表里的所有Memo字段都不读取到前台,这样来大大提高了读取数据时的效率,特别是当Memo字段里内容多的时候,可是当我们需要Memo字段里的内容时怎么办呢?
这点是我们一直以来不管用远程视图、SPT还是用CursorAdapter做C/S程序时的痛苦矛盾之处,现在我们终于在VFP9的CursorAdapter里找到了完美的解决办法。
先用文字来说明一下VFP9的CursorAdapter的解决方法,当CursorFill()时,所有Memo字段的内容全部为空,以提高读取记录时的效率,但当光标移动到这条记录的这个字段时,自动从后台读取这条记录的当前Memo字段的内容到前台,填充进CursorAdapter里,以我实际操作下来的感觉,几乎根本感觉不到这个读取过程,而数据确确实实读到了前台。
整个设置过程如下:
1)oCa.FetchMemo=.F.
2)oCa.FetchMemoDataSourceType=oCa.DataSourceType
3)oCa.FetchMemoDataSource=oCa.DataSource
4)oCa.FetchMemoCmdList这个是最关键的,也是最麻烦的:
oCA.FetchMemoCmdList="f1<SELECTf1FROMtestCAMemoFetchWHEREf0=?
EVALUATE(this.RefreshAlias+'.f0')>,f2<SELECTf2FROMtestCAMemoFetchWHEREf0=?
EVALUATE(this.RefreshAlias+'.f0')>"
f1,f2这里是Memo字段名简称
f0一般是关键字段名
this.RefreshAlias可以是this.Alias
我翻译一下,就应该比较好理解了,意思如下:
”Memo字段名<selectMemo字段名From后台表名where关键字段名=?
前台的Alias名.关键字段内容>,…..”
只要设置好了以上属性,当前台记录移动到Memo字段时CursorAdapter会自动调用DelayedMemoFetch(),来读取Memo字段内容。
注意:
1)DelayedMemoFetch如果按照以上设置,只是从现象上看实现了“DelayedMemoFetch”,实际上并未真正提高效率,Memo型内容还是一次下载到了本地,这个估计也能算是一个BUG吧,目前的解决办法是,例如后台是SQLServer数据库,
原oCa.SelectCmd为:
SELECTField1,Field2,MemoField1,MemoField2,MemoField3FROMTabelName
改成
SELECTField1,Field2,cast(''astext)asMemoField1,cast(''astext)asMemoField2,cast(''astext)asMemoField3FROMTableName
DelayedMemoFetch其他设置不变,这样就真正实现了“DelayedMemoFetch”。
2):
如果是异步的话,使用DelayedMemoFetch时,要另外设置不同的oCa.FetchMemoDataSource
3):
"DelayedMemoFetch"功能不光针对Memo有效,对VFP9新增的字段类型blob同样有效。
RecordRefrsh()、Auto-Refresh和DelayedMemoFetch()此三项功能是SPT无法做到的,RecordRefrsh()、Auto-Refresh做到了前台Cursor的行级(记录级)刷新,而DelayedMemoFetch()实现了字段级的刷新,合理使用好此三项功能,能极大的提高整个C/S系统的效率,降低网络和服务器开销。
7.blob
VFP9新增加了几种数据类型,其中一种就是blob--二进制大型对象,以前我们在后台保存图片的时候,在保存读取前后有一个FileToStr()和StrToFile()过程,这使得编程相当麻烦,同时中间过程中还要产生临时文件,现在我们完全可以利用VFP9新增加的这个数据类型,结合VFP9Image控件新增加的PictureVal属性,直接将blob类型绑定在Image控件的PictureVal属性上,当中无需做任何转换。
具体用CursorSchema做时只需在oCa.CursorSchema里设置相应字段类型为(W)型,同时设置oCa.UseCursorSchema=.T.即可。
据具体测试,如果后台是SQLServer,blob型最佳对应类型是Image型,当然用Text也可以,但发现,用Text型放置大图片会发生丢失字节的现象,而放置其他文件却没什么问题。
放置图片的blob字段在报表中的应用:
此主题相关图片如下:
此主题相关图片如下:
示例程序如下:
CLOSEALL
CLEARALL
LOCALcDeafultPath,cDataPath
PRIVATEoRLASReportListener
cDefaultPath=ADDBS(JUSTPATH(SYS(16)))
SETDEFAULTTO(cDefaultPath)
cDataPath=HOME()+'Samples\Tastrade\'
*--创建示例数据表
SELECTFirst_Name,;
Last_Name,;
CAST(FILETOSTR(cDataPath+Photo_File)ASBlob)ASPhoto;
FROM(cDataPath+'data\Employee.dbf');
INTOCURSORTempCursor
oRL=NEWOBJECT("Photolistener")
oRL.vPictureVal="TempCursor.Photo"
SELECTTempCursor
REPORTFORMTestFrxOBJECToRL
USEINTempCursor
DEFINECLASSPhotolistenerASReportListener
oImage=.NULL.
vPictureVal=''
ListenerType=1
PROCEDUREINIT
THIS.oImage=CREATEOBJECT("Image")
THIS.oImage.PictureVal=THIS.vPictureVal
ENDPROC
PROCEDUREImageValue
THIS.oImage.PictureVal=EVALUATE(THIS.vPictureVal)&&此处刷新字段内容
ENDPROC
ENDDEFINE
8.MapVarchar属性
Varchar也是VFP9新增加的数据类型,以前如果我们后台是SQLServer,SQLServer里有varchar字段类型,如果我们在后台设置了varchar型,可在前台CursorAdapter里只能映射为Char型,所以后台的Varchar优点无法直接利用,如果要实现,只能设置oCa.ConversionFunc="Field1TRIM,Field2TRIM.....",这样既麻烦,又容易出错,现在正是由于VFP9也有了varchar数据类型,这一切将变得非常轻松简单,将oCa.CursorSchema里原来的(C)型,改成(V)型,然后设置oCa.MapVarchar=.T.,设置oCa.UseCursorSchema=.T.即可。
以上8点是我认为是VFP9CursorAdapter类最具人性化和效率化的方面的功能增强,下面再说说其他几个C/S方面的功能增强。
1.RecordsFetched 和 FetchIsComplete
以前我们读取大批量记录的时候,如果想要做一个人性化的进度条,是一件非常不容易的事情,一般只能采取异步方式,先读取记录总数,然后用一个循环,
lnResult=SQLEXEC(lnHandle,“SELECT*FROM….WHERE…”,“Temp”)
DOWHILElnResult=0
liResult=CURSORGETPROP("FetchSize")
此处写入进度条代码
ENDDO
这样做,效果是出来了,可是也有缺陷,异步其实变成了同步。
现在VFP9在CursorGetProp()里增加了两个参数,RecordsFetch和FetchIsComplete,意思和使用方法如下:
RecordsFetched返回读取远程表过程中目前所传回来的记录数目
例如:
lnResult=CURSORGETPROP("RecordsFetched")
FetchIsComplete表示读取过程是否已经完成
如果已完成 = .T.
例如:
llResult=CURSORGETPROP("FetchIsComplete")
有了这两个属性,要做一个进度条就轻而易举了,而且能实现异步功能不丧失的效果。
RecordsFetch和FetchIsComplete应该还有其他用处,留待我们一起来慢慢挖掘吧。
2.ASQLHANDLES()函数
VFP9以前要想得到当前运行程序里使用了多少句柄,将时件非常不容易的事情,VFP9里这又变成了一件轻松简单的活。
LOCALlnHandleSum,lnI
LOCALARRAYlaHandle[1]
lnHandleSum=ASQLHANDLES(laHandle)
'共有连接:
'+TRANSFORM(lnHandleSum)
'连接句柄分别为:
'
FORlnI=1TOlnHandleSum
laHandle(lnI)
ENDFOR
3.SQLEXEC()里增加了一个aCountInfo参数
VFP9以前,当我们向后台发送Insert,Update,Delete命令以后,要想知道到底执行了几条记录。
如果后台是SQLServer,只能通过再发送一条SPT命令lnResutl=SQLEXEC(lnHandle,"select@@ROWCOUNT",lcTemp),然后再通过临时表来取得,非常麻烦。
VFP9里,SQLEXEC()函数增加了这个参数,
SQLEXEC(nStatementHandle[,cSQLCommand[,cCursorName[,aCountInfo]]])
aCountInfo是一个数组,包含了向后台发送SPT命令所影响的记录总数。
4.SQLIDLEDISCONNECT()这是我认为VFP9中极其有意义的C/S功能增强。
尤其是对CursorAdapter,当然对SPT和远程视图也同样适用。
SQLIDLEDISCONNECT()从字面上理解是暂时中断连接。
刚开始,我始终未能理解其意思,可当亲手做了实验以后,就不得不惊叹其功能之强大了。
以前在VFP8下我曾仔细做过CursorAdapter的断线重连的测试,得出结论,CursorAdapter断线重连以后,当前数据可以向后台更新,但已经无法CursorRefresh()了,只能重新CursorFill()以后才行,但重新CursorFill()以后,前台的Cursor等于是重新生成了,这对前台如果是用GRID来绑定Cursor时尤为不便。
现在终于盼到了-----SQLIDLEDISCONNECT(),当CursorFill()、CursorRefresh()或者RecordRefresh()以后SQLIDLEDISCONNECT(lnHandle),此时检查服务器,确实此句柄已经不存在了,和服务器完全脱离了关系,为了保险起见,把网线拔了,过一段时间再插上,再对CursoraAdapter进行数据更新,提交后台,然后在前台执行CursorRefresh()或者RecordRefresh(),这个时候检查服务器,连接句柄自动建立成功了,而且数据确实更新成功并重新刷新。
再用SPT做了测试,同样得到了完美的结果。
综上所述,一旦执行了SQLIDLEDISCONNECT(),这个句柄就处于休眠状态,此时完全和服务器脱离了关系,一旦发生前台向后台请求任何的任务,此时VFP将无需任何条件、无需任何人工干预的自动唤醒此连接,且句柄号不变。
此项功能在用户数较多或者网络环境较差的情况下尤其有用,特别是在降低服务器的资源消耗方面有着非常大的作用。
后记:
当初VFP9Beta发布的时候,我匆匆写下了此文,其中有很多地方未经过深入细致的测试,现在VFP9正式版已经发布,经过在实践应用中发现很多以前认识不够或错误的地方,今天终于抽空重新改写了此文,希望以前的一些认识不够深入之处未对其他狐友造成误导!
在此过程中受到动感游标狐友:
dupeiji、edwin7521、chxking、net_steven的大力帮助,在此一并谢过。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Visual FoxPro CSODBC方面极富人性化的增强 CSODBC 方面 极富 人性化 增强