版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第十二章 并发共享访问编程及其它 12.1 多用户环境及多用户操作函数、命令112.2 使用数据工作期512.3 用缓冲(Buffering)访问共享数据712.4 用事务处理(Transaction)管理更新数据1212.5 Internet与VFP的Active Document16如果建立的应用程序在网络环境中的多台计算机上运行,或者一个表单的多个实例对相同数据进行访问,这就要进行共享访问程序设计。共享访问不仅能为用户使用数据和数据共享提供更有效的方法,而且在必要时可对访问进行限制。VFP具有对数据的共享或独占访问;锁定选项;数据工作期;记录缓冲和表缓冲以及事务处理等功能。尽管这些功能主
2、要用在共享环境里,但在单用户环境下也可以使用。 12.1 多用户环境及多用户操作函数、命令FoxPro 2.5以上的FoxPro和VFP都是多用户版本,没有单用户版本了。在一个网络环境(例如Novell网文件服务器)中,一个工作站(Workstation)上的用户试图访问一个正被另外的工作站用户访问的记录或文件就会产生碰撞(Collision)。当这种情况出现时,如果多于一个用户打算修改这个记录,则会导致损坏数据的结果。于是便出现了象APPEND、APPEND FROM、ALTER TABLE、INDEX、INSERT、JOIN和UPDATE、UPDATE-SQL等能够自动加锁(隐含加锁)整个
3、表,象APPEND BLANK、APPEN FROM ARRAY、INSERT-SQL等能自动加锁表头,象APPEND MEMO、DELETE、DELETE-SQL、GATHER、BROWSE、CHANGE、EDIT、MODIFY MEMO、READ、RECALL、REPLACE、SHOW GETS等能自动加锁记录的命令(CURSORSETPROP()取决于缓冲进行自动加锁),防止其它工作站破坏用户正访问的数据。但如果不及时解锁,又可能出现死锁(Deadly Embrace)的情况,即:当一个用户锁定了一个记录并希望访问一个正被第二个用户加锁了的记录,或反之,第二个用户正试图访问第一个用户锁定
4、了的记录,等等。死锁的出现是很少的,但随着一个记录加锁的时间的增加,它的可能性也在增加。VFP提供了如下一些人工明显文件加锁、人工明显记录加锁和解锁以及捕捉错误的函数和命令,可有效地解决上述问题(要求只读访问一个表的命令,不用文件加锁和记录加锁)。1表文件加锁的函数FLOCK()格式:FLOCK()说明:该函数试图将当前或指定工作区的表文件锁定(锁定全部记录)。如果加锁成功,返回.T.(真),这样可读写该表,其它用户只能读不能写。如果加锁不成功,则返回.F.(假),表示这个表或表中的一个记录早已被其它用户锁定了。函数返回类型逻辑型。用户可以根据情况用UNLOCK、USE、CLEAR ALL或者
5、CLOSE DATABASE等命令来关闭表。在缺省情况下,FLOCK()只对一个表进行一次锁定尝试。用SET REPROCESS,当第一次尝试失败时自动地再次锁定这个表。SET REPROCES确定尝试的次数和再次尝试的间隔时间(详见VFP软件的Help)。用户还可以完全独占地加锁表,防止其他用户访问它(即,将其他用户的只读访问权也剥夺掉),用SET EXCLUSIVE ON 和USEEXCLUSIVE命令便可独占表。在前面章节,介绍表索引时,已这样用过独占设置命令。2表记录加锁的函数RLOCK()格式:RLOCK(|,)说明:VFP的RLOCK()函数可锁定多个记录。其中任选项指定一个或者多
6、个记录号,并用逗号将它们分开,这样RLOCK()函数将试着给这几个记录加锁。例如,要给表中的前5个记录加锁,就必须含有1,2,3,4,5。不选,只给当前记录加锁。用户要给多个记录加锁必须将SET MULTILOCKS设置为ON,并且要给出记录所在工作区号或表的别名。用户还可将记录指针移到相应记录,然后给出RLOCK()函数,重复以上过程给其它记录加锁,同样可达到给多个记录加锁的目的。在VFP中,可将记录号设置为0,这样用户可给表头加锁,锁定库头时间一定要短,因为一旦锁定了库头,其他用户便不能在表中添加或删除记录了,但可修改字段内的数据。表锁定命令锁定整个表,比表头锁定命令更严厉。当前或指定工作
7、区表中由所指定的记录都加上锁,RLOCK()将返回.T.(真),如果中的一个或者多个记录不能被锁定,RLOCK将返回.F.(假),并且不给任何一个记录加锁。在上述两种情况下,仍然保留以前已经存在的记录锁定。函数返回类型逻辑型。在网络中,只有加锁者本人才能对加锁记录进行读写操作,这些记录对于其他用户来说是只读的。记录锁定只能由加锁者本人打开。用户可以通过给出UNLOCK命令,关闭表或者退出VFP系统都能够给记录解锁。命令UNLOCKRECORDINALL可以用来解开当前工作区、指定工作区的指定记录或所有工作区的记录锁定。一般RLOCK()为记录进行一次加锁尝试,多次加锁尝试的处理与FLOCK()
8、的多次尝试相同。LOCK()与RLOCK()完全等同。3检测ON ERROR语句捕捉的出错号ERROR()的函数格式:ERROR()说明:ERROR()返回最近的一个错误号。在ON ERROR命令被激活的情况下,ERROR()返回一个非0值。函数返回类型数值型。当程序执行时遇到了错误(如隐含加锁失败等),可用ON ERROR 程序中的ERROR()函数查明错误的类型,用MESSAGE()函数可返回相应的错误信息。ERROR()返回值可用RETURN或RETRY来复位,复位为0。4检测 ON ERROR语句捕捉的出错号对应的出错信息的函数MESSAGE()格式:MESSAGE(1)说明:此函数功
9、能是:以字符串的形式返回当前的错误信息。任选项1,表示可返回引起错误的源程序命令行内容。如果此程序代码不能用,则MESSAGE(1)将返回以下几种形式之一。(1)如果此行是宏替换的,返回整个程序行。(2)如果此行包含的命令没有任何附加的子句时,返回此命令。(3)如果此行包含有命令和附加的子句时,将返回此命令和后面三个小点()。本函数返回类型为字符型。和ERROR()函数不一样,MESSAGE()不能由RETURN或者RETRY重新设置。5关于多用户的系统的函数SYS()格式:SYS()说明:详见4.7节。另外,还有几个重要的与多用户函数相关的多用户命令:如SET PRINTER TO可设置网络
10、打印等;RETRY命令可将控制返回给调用的程序并且在调用不是重新执行最后一行(RETRY)外,RETRY命令类似于RETURN(返子程序)命令。当一组命令必须重复直到一个确定的条件为真时,RETRY命令特别有用。比如RETRY在错误处理程序中是很用的,在给记录或者文件加锁的时候也是这样,RETRY频繁地执行同一个命令,直到成功地给记录或者文件加上锁为止。用户可以使用SET REPROCESS来控制记录或者文件加锁函数的执行。在大多数网络环境中,使用SET REPROCESS更为可取。例12.1:使用APPEND BLANK隐含加锁文件头和在与其他用户来“碰撞”时进行捕捉错误的处理。SET EX
11、CLUSIVE OFF&设置为共享环境ON ERROR DO fixUSE VideoAPPEND BLANKON ERROR*下面的Fix.PRG是处理上面错误的子程序IF ERROR()=108&108错误是文件被另外的用户在用 23, 0 SAY请等待去添加一个记录RETRYELSE 23,0 SAY请去咨询你的系统管理员,关于这个错误是什么原因 +MESSAGE()WAITENDIF例12.2:共享表情况下的文件加锁。SET EXCLUSIVE OFFSET REPROCESS TO 0USE VideoIF FLOCK()REPLACE ALL Cost_rent WITH Coxt
12、_rent+1.00UNLOCKELSE 22, 0 SAYFile is use by another。ENDIF在上面例子中,表Video为共享访问而打开。FLOCK()函数与IFELSEENDIF结构结合去确定锁定状态。如果文件由于没有另外的用户使用而加锁成功,则执行REPLACE ALL命令,并且租用一个录像(Video)带的价钱上涨1.00美元。完成REPLACE ALL操作后,执行UNLOCK命令去解除文件锁定。如果文件由于另外的用户已使用而加锁失败的话,则出现一个“文件被另外的人使用”的屏幕信息。例12.3:记录加锁。SET EXCLUSIVE OFFUSE VideoLOCAT
13、E FOR Cost_rint=25.00DO WHILE.NOT.LOCK().and.TIME1000TIME=TIME+1ENDDOIF TIME 1000REPLACE Cost_rent WITH Cost_rent+5.00ELSE 23 ,O SAY记录不能加锁,稍后再试。ENDIF 上面的例子中,LOCATE命令找到Video库中第一个Cost_rint=25.00元的记录,并用Lock()函数与DO WHILEENDDO循环结构结合去尝试锁定该记录。如果加锁不成功,则计次数变量TIME加1,再循环去加锁,直到LOCK()为真(.T.)即.NOT.LOCK()为假(.F.)时跳
14、出循环(或者加了1000次也不成功,即TIME1000,也跳出循环)。若TIME1000时加锁成功,则执行将该记录租金字段加5.00元的REPLACE语句。否则在屏幕上显示“记录不能加锁,稍后再试”的信息。 12.2 使用数据工作期为确保共享环境中的每个用户都具有安全、正确的环境,确保表单的多个实例能独立操作,VFP提供了数据工作期。数据工作期是对当前动态工作环境的描述。可以将数据工作期看成是一个小型的数据环境,这个环境是在一台机器上运行的一个开放的VFP工作期。每个数据工作期包括:(1)表单的数据环境中各项的备份。(2)表示打开的表、索引和关系的临时表。请考虑当在多用户应用程序的各自工作站同
15、时打开相同的表单时,会发生什么,这样可以很容易理解数据工作期的概念。这种情况下,每个工作站运行一个独立的VFP工作期,因此有自己的工作区设置以及自己表示打开的表、索引和关系的临时表。但是,如果你在一个机器上,同一个VFP工作期,打开单个项目中的同一个表单的多个实例,则这些表单共享默认的数据工作期,它代表了单个的动态工作环境。在同一个VFP工作期中打开的表单的每一个实例使用相同的工作区设置,并且在一个表单实例中移动工作区中的记录指针会自动影响相同表单的其他实例。 12.2.1 使用私有数据工作期 如果想更多地控制表单的多个实例,可以使用私有数据工作期。当表单使用私有数据工作期时,VFP为应用程序
16、创建的表单、表单集或工具栏中的每个实例创建一个新的数据工作期。每个私有数据工作期包括:(1)表单的数据环境中每个表、索引和关系的独立备份。(2)数目不限的工作区。(3)独立于表单基表的每个备份表的记录指针。若要使用私有数据工作期: 在“表单设计器”中,将表单的DataSession属性设置为“2_私有数据工作期”。或者, 在代码中将DataSession属性设置为2。例如,可键入:frmFormName.DataSession = 2当表单使用的是私有数据工作期时,在单个的机器上,单个的VFP工作期中打开表单的每个实例使用自己的数据环境。使用私有数据工作期类似于在不同的工作站上同时运行同一个表
17、单。 12.2.2 识别数据工作期 每个私有数据工作期是单独识别的。可以在“数据工作期”窗口中查看每个数据工作期的内容。也可以通过在Load事件代码中的命令改变数据工作期的说明。使用DataSessionID的运行时属性,可以查看每个数据工作期限的识别号。下面的示例显示名为frmMyForm的表单的DataSessionID属性。 DO FORM frmMyForm? frmMyForm .DataSessionID DataSessionID属性只是用来识别特殊的数据工作期。不要更改一个表单实例的DataSessionID属性, 当更改DataSessionID属性时,与数据绑定的控件会丢失
18、它们的数据源。 12.2.3 使用多个表单实例更新数据 私有数据工作期生成各自独立的工作区,工作区包含了表单的表、索引和关系的独立备份,表单的每个备份引用了相同的基表和索引文件。当用户从表单的一个实例中更新记录时,更新该表单引用的基表。当定位到更改的记录时,就可以看到表单另一个实例所作的更改。 如果在一个私有数据工作期对记录或表进行了锁定,其他私有数据工作期就不能再进行锁定。例如,数据工作期1的用户锁定了一个记录,数据工作期2的用户就不能锁定这个记录了。如果数据工作期1的用户以独占方式打开了一个表,数据工作期2的用户就不能打开这个表了。通过遵守其他数据工作期所作的锁定,VFP可以保护基表更新的
19、完整性。 12.3 用缓冲(Buffering)访问共享数据如果希望在更新时保护数据,可以使用缓冲技术。在多用户环境下,VFP的记录缓冲和表缓冲技术可以保护对单个或多个记录所做的数据更新以及数据维护工作。缓冲区可以自动测试、锁定以及解锁记录或表。借助缓冲技术,可以很容易地检测并解决数据更新操作过程中所遇到的冲突:当前记录被复制到一个由VFP进行管理的内存或磁盘区域,其他用户仍然可以同时访问原来的记录,当离开记录或以编程方式更新该记录时,VFP将准备锁定该记录,确认其他用户没有做修改,然后写入编辑结果。在试图更新数据时,还必须注意解决冲突,在冲突时防止编辑结果直接写入原来的表。12.3.1 缓冲
20、编辑结果 在启动缓冲之前,应根据实际需要选择缓冲方法和锁定选项。一旦启用缓冲,则在它被废止或关闭表之前一直保持有效。1.选择缓冲方法VFP有两种类型的缓冲:记录缓冲和表缓冲。(1)若一次只对一个记录进行访问、修改或写操作,一般应选择记录缓冲。在多用户环境中,记录缓冲能够提供适当的有效检查机制,对其它用户所做的数据更新操作影响最少。(2)若要对多个记录(一个表中处理多个记录或在一对多关系中处理子记录)的更新使用缓冲,应选择表缓冲。(3)若要对已有数据提供最大程度的保护可使用VFP事务。可以单独使用事务,但是如果将事务和记录缓冲或表缓冲命令一起使用,会获得更好的效果(事务详见下节)。2.选择锁定方
21、式VFP有两种锁定方式提供缓冲:保守式和开放式。在多用户环境中,保守式缓冲能防止其他用户在对某一特定记录或表正进行修改时访问它。保守式缓冲为单个记录的修改提供最安全的工作环境,但是会降低用户的操作速度。开放式缓冲是更新记录的有效方法,因为锁定只在写记录时生效,这样在一个远程表上使用记录或表缓冲时,VFP将强制使用开放式锁定。3.启用记录缓冲和表缓冲可用CURSORSETPROP()函数且设置Buffering属性值,来决定缓冲和锁定的方法,并启用缓冲。(1)启用保守式记录锁定若要启用保守式记录锁定,可以设置:=CURSORSETPROP(Bufferimg,2)VFP在指针位置锁定记录。如果锁
22、定成功,VFP将记录放入缓冲区并允许编辑。当移动记录指针或发出TABLEUPDATE()命令时,VFP将把缓冲记录写入原来的表。(2)启用开放式记录锁定(3)对多记录(即表)启用保守式锁定若要对多个记录启用保守式锁定,可以设置:CURSORSETPROP(Buffering,4)VFP在记录指针位置锁定。如果锁定成功,VFP将把该记录放入缓冲区并允许编辑。使用TABLEUPDATE()命令将把缓冲记录写入原来的表。(4)对多个记录(即表)启用开放式锁定若要对多个记录启用开放式锁定,可以设置:CURSORSETPROP(Buffering,5)在发出TABLEUPDATE()命令之前,VFP把记
23、录写入缓冲区,并允许编辑,然后VFP对缓冲区内的每一记录执行下列操作: 对每一个已编辑记录锁定。 一旦锁定成功,即对磁盘上的每一个记录的当前值与原来的缓冲区值进行比较。 如果两值相同,将编辑结果写入原来的表。 两值不同,给出错误信息。在启用表缓冲之后,VFP只在TABLEUPDATE()命令之后更新。对于表,Buffering的默认值为1(无缓冲);对视图,默认值为5。如果使用缓冲访问远程数据,则Buffering属性可以是3(开放式行缓冲)或5(开放式表缓冲)。注意:对所有除以外的缓冲方式,设置MULTILOKS为ON。4.在表缓冲区中追加和删除记录可以在启用表缓冲之后追加和删除记录。追加的
24、记录(用APPEND或APPEND BLANK命令)将添加到缓冲区末尾。要访问缓冲区中所有记录,则使用RECNO()函数,RECNO()函数根据追加到表缓冲区中的记录情况返回序列负值。比如,如果启用了表缓冲,编辑记录7、8、9,然后追加三个记录,则此时缓冲区将包含RECNO()的值为7、8、9、-1、-2和-3。在使用表缓冲时,可以用带负RECNO()值的GO命令来访问指定的追加记录。例12.4:对前面的示例,可以键入:GO 7&转到第一个缓冲记录GO 3&转到第六个缓冲记录(即第三个追加记录)若要从 表缓冲区中移去追加的记录:可先使用带负值的GO命令将记录指针定位到要删除的记录;再用DELE
25、TE命令将该记录加上删除标记;最后用TABLEREVERT()函数将该记录从缓冲区中移去。若要从表缓冲区中移去所有追加的记录,使用带(.T.)值的TABLEREVERT()函数。TABLEREVERT()把追加的记录从表缓冲区中移去,而不将这些记录写入表。TABLEUPDATE()命令将所有当前的记录写入一个表,包括已打上删除标记的记录。 12.3.2 执行更新 在选择缓冲方法和锁定类型之后,可采用代码方式启用记录或表缓冲。代码放置在表单或表单集的Init过程,然后把用于更新操作的代码放入适当控制项的相应方法中。要把编辑结果写入原来的表,可以使用TABLEUPDATE()。由于规则限制,造成对
26、表的更新操作失败之后,要取消编辑结果,可以使用TABLEREVERT()。TABLEREVERT()即使在没有明确启用表缓冲的情况下都有效。例12.5:下面的例子说明在启用保守式记录缓冲的情况下,如何更新记录OPEN DATABASE MYDATA&在表单的Init代码,打开表并启用保守式记录缓冲USE MYTABLECURSORSETPROP(Buffering,2) LModified=.F.FOR nFiedNum=1 TO FCOUNT()&遍历字段,检查是否有字段进行了修改。IF GETFLDSTATE(nFieldNum)=2LModiffied=.T.&附注:此代码可以在“保存”
27、或“更新” 命令按钮的Click事件中EXITENDIFENDFORIF Lmodified&定位下一个已修改的记录nResult=MESSAGEBOX;(记录已被修改。存吗?,;4+32+256, 数据修改)IF nResult=7&提交当前值并为用户提供选项,询问是否还原对当前字段所做的修改。TABLEREVERT(.F.)ENDIFENDIFSKIPIF EOF()MESSAGEBOX(已经在表底部)SKIP -1&SKIP确保最后一次修改内容也已写入ENDIFTHISFORMRefresh 12.3.3 检测并解决冲突 在数据库更新操作过程中,特别是在共享环境下,用户可能希望确定哪些字
28、段已经更改,确定已更改字段的原有值或当前值是什么,VFP的缓冲和GETFLDSTATE()、GETNEXTMODIFIED(),OLDVAL()以及CURVAL()函数可以提供这些功能。通过它们来确定哪些字段已经更改,查找已更改数据;比较当前值、原有值及已编辑的值。这样可以决定如何处理错误或冲突。若要检测字段中所做的更改,在更新操作之后,使用GETFLDSTATE()函数,它可以对非缓冲数据进行操作,但在启用了记录缓冲的情况下,此函数更有效。可将GETFLDSTATE()用于一个表单的Skip按钮代码中。当移动记录指针时,VFP将检查记录中所有字段的状态,如例12.6所示。例12.6:LMod
29、ified=FFOR nFieldNum=1 TO FCOUNT()&检查所有字段。if GETFLDSTATE(nFieldNum)=2&字段已修改。LModified=.T.&可以在此处插入一个更新/保存例程,参阅下一个示例。EXITENDIFENDFOR若要检测并定位缓冲数据中已更改的记录,可使用GETNEXTMODIFIED()函数,它以0作为参数,查找第一个已修改的记录。如果其他用户对缓冲表进行了修改,则你的缓冲区中TABLEUPDATE()命令遇到任何修改都将导致冲突。可以用CURVAL()、OLDVAL()和MESSAGEBOX()计算冲突值并解决冲突,CURVAL()返回磁盘上
30、记录的当前值,而OLDVAL()返回记录缓冲时的原有值。在共享环境中,可以创建一个出错处理过程,比较当前值与原有值,并决定是接受用户自己的编辑结果还是将编辑结果写入原来的表之前已被其他用户修改的磁盘上的当前值。下面的例子使用这几个函数,在更新操作过程中给用户提供选择。这个例子检测第一个修改的记录开始,可以包含在表单的“更新”或“保存”按钮代码中。例12.7:“更新”或“保存”按钮Click事件代码。DO WHILE GETNEXTMODIFIED(nCurRec)0&循环遍历缓冲区。GO nCurRec=RLOCK()&锁定已修改的记录。FOR nField=1 TO FCOUNT(cAlia
31、s)&查找冲突。cField=FIELD(nField)IF OLDVAL(cField) CURVAL(cField)&比较原有值和磁盘上的当前值,请用户指示如何处理冲突。nResult=MESSAGEBOX(数据已被其他用户修改。保存变化吗?,4+48+0,被;修改的记录)IF nResult=7&如果用户选择“”否按钮,则还原此记录,然后解锁。=TABLEREVERT(.F.)UNLOCK RECORD nCurRecENDIFENDIFENDFORnCurRec=GETNEXTMODIFIED(nCurRec)&查找下一个已修改的记录。ENDDO=TABLEUPDATE(.T.,.T.
32、)&对所有记录更新。12.4 用事务处理(Transaction)管理更新数据即使使用缓冲,事情有时也会出错。如果希望保护更新操作,并从一整段代码中还原回来,可以使用事务。在应用程序中添加事务所提供的保护机制超过了记录缓冲和表缓冲提供的保护功能,它将整段代码作为一个受保护的、可恢复的单元。可以嵌套使用事务,并用它保护已操作的缓冲更新。VFP事务只能用于数据库中的表和视图。 .包装代码段 事务处理类似一层外包装,用来缓冲对内存或硬盘的数据更新操作,而不直接对数据库进行更新。实际的更新在事务结束之后进行。由于某种原因,系统不能执行对数据库的更新操作,就可以回滚整个事务,而不执行任何更新。1.控制事
33、务处理的命令VFP提供了3个控制事务处理的命令和1个函数,如表12-1所示。表 12-1命令作用BEGIN TRANSACTION初始化一个事务。ROLLBACK取消最近一个BEGIN TRANSACTION语句以来所做的全部修改。TXNLEVEL()确定当前事务的等级。END TRANSACTION锁定记录,将最近一条BEGIN TRANSACTION语句以来对数据库中表所做的全部修改写入磁盘,然后解锁记录。可以用事务缓冲对表、结构化.CDX文件以及与数据库表相关的备注文件的修改。涉及内存变量和其他对象的操作不属于事务,因此不能回滚这些操作。远程表不受事务处理命令的影响。要对远程表启用人工事
34、务,应使用SQLSETPROP(),然后用SQLCOMMIT()和SQLROLLBACK()控制事务处理。一般来说,除非采用TABLEUPDATE()包装调用,事务最好和记录缓冲一起使用,而不与表缓冲一起使用。如果在事务中使用了TABLEUPDATE()命令,那么可以回滚失败的更新操作,找到失败的原因,然后重试TABLEUPDATE()命令而不丢失任何数据,这样,就确保了更新操作一定是所谓的“要么全做,要么不做”的操作。请使用下列事务处理代码模板:BEGIN TRANSACTION* 更新记录IF lSuccess=.F.&出错ROLLBACKELSE* 确认数据&执行修改IF&出错ROLLB
35、ACKELSEEND TRANSACTIONEND IFENDIF2.使用事务使用事务的规则是:(1)事务起始于BEGIN TRANSACTION命令,以END TRANSACTION命令终止,两者不匹配会出错。(2)ROLLBACK语句前没有BEGIN TRANSACTION将出错。(3)事务处理只在数据库容器中进行。(4)如果INDEX命令改写了一个已有的索引文件,或者任一索引文件已打开,则不能使用INDEX命令。事务处理完成了下列锁定动作: 当一个命令直接或间接调用事务时,VFP将强制锁定。任何系统或用户的直接或间接命令将被缓冲,直至ROLLBACK或END TRANSACTION命令结
36、束事务操作。 如果在事务处理中使用了锁定命令,如FLOCK()或RLOCK(),则END TRANSACTION语句将不会解锁。因此,必须明确地解除任何在事务处理中进行的明确锁定。3.嵌套事务处理对于分隔在不同迸发进程中的表,嵌套事务可以为表的更新操作提供逻辑组。事务处理命令BEGIN TRANSACTIONEND TRANSACTION不需要在同一函数或过程中。下面的规则适用于嵌套事务处理:(1)可以嵌套五层BEGIN TRANSACTIONEND TRANSACTION。(2)直到最外层的END TRANSACTION被调用时,才执行嵌套事务中的更新。(3)在嵌套事务中,一个END TRA
37、NSACTION只对最近BEGIN TRANSACTION所引起的事务进行操作。(4)在嵌套事务中,ROLLBACK语句只对最近BEGIN TRANSACTION所引起的事务进行操作(5)在嵌套事务中对同一数据的更新操作,最内层的更新优先于嵌套事务处理块中的其他更新。例12.8:本例,因为在嵌套事务中所做的修改没有写入磁盘,而写入事务处理缓冲区,内层事务处理将改写外层事务处理对同一STATUS字段所做的修改。BEGIN RANSACTION&事务UPDATE EMPLOYEE;&第一次修改SET STATUS=Contract;WHERE EMPID BETWEEN 8001 AND 1000
38、BEGIN TRANSACTION&事务UPDATE EMPLOYEE;SET STATUS=Exempt;WHERE HIREDATE1998-01-01&改写END TRANSACTION&事务END TRANSACTION&事务4.保护远程更新在对远程表进行数据更新的过程中,事务可以避免系统造成的错误。例12.9:本例使用了事务包装对远程表的数据写入操作。hConnect=CURSORGETPROP(Connecthandle)&获得连接句柄。=SQLSETPROP(hConnect, transmode,DB_TRANSMANUAL)&启用人工事务。lSuccess=TABLEUPDA
39、TE(.T.,.F.)&非强制更新所有记录。IF lSuccess=.F.&如果更新失败,在连接上回滚临时表的=SQLROLLBACK(hConnect)事务。=AERROR(aErrors)&从AERROR()中获得错误信息。DO CASECASE aErrors1,1=1539&如果是触发器失败,进行相应处理。CASE aErrors1,1=1581&如果是字段不接受null值,进行相应处理。CASE aErrors1,1=1582&如果是违反了字段规则,进行相应处理。CASE aErrors1,1=1585&如果是记录已被其他用户修改,nNextmodified=GETNEXTMODIF
40、IED(0)进行相应处理。DO WHILE nNextmodified0&从第一个记录开始,循环遍历所GO nNextmodified有已修改字段。FOR nField=1to FCOUNT()&检查每个字段是否更改。cField=FIELD(nField)IF OLDBAL(cField);&比较缓冲值和磁盘上的值,然后CURVAL(cField) 出现话框。nResult=MESSAGEBOX;(数据已经被其他用户;修改。;保留修改吗?,4+48,;被修改的记录)IF nResult=7&如果用户响应“否”按钮,=TABLEREVERT(.F.)还原一个记录。ENDIFEXIT&脱离FOX
41、 nField循环。ENDIFENDFORnNextmodified=;&获得下一个已修改的记录。GETNEXTMODIFIED(nnextModified)ENDDO=TABLEUPDATE(.T.,.T.)&强制更新所有未还原记录。=SQLCOMMIT(hConnect)&提交事务。CASE aErrors1,1=1700&如果记录正由其他用户使用,进行相应处理。CASE aErrors1,1=1583&如果违反行规则,进行相应处理。 CASE aErrors1,1=1884&如果违反唯一索引规则,进行相应处理。OTHERWISE&否则,出现对话框。=MESSAGEBOX(;Unknown
42、 error message:;+STR(aErrors1,1)ENDCASEELSE=SQLCOMMIT(hConnect)&提交事务(结束事务处理)。ENDIF 12.5 Internet与VFP的Active Document 本节主要讲述VFP的Active Document与国际互联网(Internet)以及将VFP作为应用程序的查询引擎(使用VFP作为数据源)在Internet上工作的问题。 12.5.1 用VFP在Internet上工作 在Internet上展开应用程序VFP还有一个关键运用是将Visual FoxPro应用程序展开到WWW(World Wide Web)上,使用
43、VFP作为一个WWW查询引擎。对于能够访问你的Web服务器的任何人,无论是来自Internet或是通过分公司的内部网,都可以使其方便地利用你的VFP数据库的功能。假如,用户要建立一个Web站点或Internet服务器,想做一个现存的雇员(employee)目录。雇员们的浏览者会被指点去查索雇员信息页,显示的HTML页面包含要求键入查索条件的文本框。为了执行查索,用户应该键入雇员的姓名、电话、部门、职位、或者雇员具有的任何其它信息,然后选择Search Now(现在搜索)按钮。过一会儿,便可看到显示出满足查索条件的那些雇员的列表。这些页面结构用来代替静态的HTML的妙处在于一旦数据库中的数据被更
44、新,它便立即被“印刷”到Web,不存在更新HTML页的潜在周期。2如何将VFP个为Web网的查询引擎一般,为了使用VFP作为Web的一个数据库服务器,需要如下组件: 一个带有HTTP服务、Microsoft Windows2000操作系统下的Web服务器(IIS)。 一个可以作为Automation服务器(见第三章)被调用的VFP应用程序,该应用程序能够运行在可被Web服务器访问的任一服务器上。 一个显示查询结果的工具,该工具经常包含一个可插入数据的Web页面模板。VFP在Web上的查询事件序列一般包括:(1)通过将一个Web浏览器的指针指向某查询页面,用户的应用程序将显示出该页面。该查询页面
45、包含用户想要的任意文本和图形,也包括能够输入查询字串的文本框。(2)用户选择“开始查询”按钮。那么已完成的表单上的数据和Web页面查询应用程序的名称将被传送到Web服务器上进行处理。(3)Web服务器使用ISAPI(全球网服务器API)协议来调用应用程序,并将包含查询信息的一个参数传给应用程序。(4)应用程序查询数据库。当找到查询结果后,将其插入到Web页面模板中,然后将该Web页面作为一个字符流返回给服务器。(5)Web服务器将查询结果页面传递给进行查询初始化的浏览器。(6)浏览器向用户显示查询结果页面。如果已经建立了Web页面,那么处理的绝大多数步骤是相似的。假设你了解如何建立Web页面,
46、那么你会发现建立这些页面的处理过程相当容易。有关使用VFP作为Web网的查询引擎的详细内容,请参阅Visual FoxPro的APISAMPLESSERVERSFOXISAPI目录下的示例程序FOXISAPI.DLL。并参考该目录下的README.TXT文件了解如何运行该程序。3WWW搜索页向导VFP的“WWW搜索页向导”创建一个Web页,允许Web页的访问者从VFP表中搜索和检索记录。向导会请你指定要搜索的表、搜索的字段,以及如何编排所创建Web页格式的信息。该向导可从“工具”菜单中“向导”的“Internet搜索向导”进入。向导创建一个HTML(超文本识别语言)页,用来输入搜索信息,创建一
47、个参数化查询,可以从你的表中检索记录,还能创建一个结果页,显示查询检索的记录。注意:向导建立的查询只作用=操作符,而不用LIKE操作符。因此,你在Web页的搜索域中不能输入通配符,例如*或%。使用通配符会返回空的结果集合。若要运行WWW搜索页向导,在“命令”窗口中键入下列命令:DO HOME()+TOOLSINETWIZWWWPAGE.APP 12.5.2 VFP的Active Document VFP可以创建Active Document,利用Active Document则可以在Web浏览器宿主程序(如Microsoft Internet)中查看非HTML文档。因此,使用Active Do
48、cument技术可以在一个Active Document宿主程序中查看多种类型的文档。Active Document是一种特别类型OLE(见第十三章)可嵌入文档,显示在Active Document宿主程序的整个客户区中,并且与宿主程序合并菜单。Active Document具有完整的结构,其功能如下:(1)Active Document总在现场激活。(2)Active Document菜单和工具栏命令可以路由到Active Document宿主程序。(3)使用Internet Explorer查看时,Active Document可以实现同其他网页的无缝集成。(4)对应将纯Visual Fo
49、xPro客户应用程序迁移到使用基于HTML客户界面的Active Platform应用程序,Active Document迈出了革命性的一步。1创建Active DocumentVFP Active Document是从VFP项目中创建的应用程序(.app),它与其他应用程序(.app)略有差别,主要是:Active Document的“主文件”必须设置为一个基于ActiveDoc基类的类,而其他种类的应用程序则需要一个程序或表单作为主文件。尽管任何应用程序都可以在Internet Explorer中运行,但是只有基于ActiveDoc基类的应用程序,才支持那些提供与Active Docume
50、nt宿主程序进行通讯的属性、事件和方法程序。例如,当Active Document 被其宿主程序释放时,将发生Container Release事件。可以在此事件中添加代码,以便在释放Active Document之前关闭文件、完成事务处理,并进行其他的清理工作。若要将主文件设置为一个基于ActiveDoc基类的类,可向项目中添加可视类库(.vcx);单击可视类库(.vcx)名称左边的加号(+),展开该类库; 选中基于ActiveDoc基类的类,在该类上单击鼠标右键,然后从快捷菜单中选择“设置主文件”命令。2ActiveDoc对象和事件序列当VFP Active Document运行在Inte
51、rnet Explorer中时,将从ActiveDoc基类创建ActiveDoc 对象,该ActiveDoc对象响应调用ActiveDoc基类的事件和方法程序。Active Document事件序列是:在Internet Explorer中打开Active Document应用程序时,Active Document运行并产生该Active Document的Init事件,然后产生其ShowDoc事件。如果Internet Explorer成功地包容了Active Document,将产生其Run事件。一般情况下,Active Document程序代码应该放在这个事件中。因此,通常Run事件中包
52、含有代码用来执行菜单代码、执行应用程序中的主表单,并包含READ EVENTS启动事件处理过程,如标准的VFP应用程序一样。如果关闭Internet Explorer,将生成HideDoc事件,然后生成Container Release事件。3Active Document中的表单和菜单VFP Active Document的用户界面由程序代码定义。通常情况下,VFP表单应该使用初始的用户界面。Active Document中的表单显示在Internet Explorer提供的客户区。可以让表单充满此客户区。如果此客户区比Active Document 视口(包含表单上所有控件的方块区域)小,
53、必须显示滚动条时,应设置Scrollbars属性为3。在VFP Active Document中运行菜单代码时,该菜单将按照具体的菜单合并规则与Internet Explorer的菜单合并。Active Document菜单与Internet Explorer的菜单合并后,Active Document菜单就像传统的VFP应用程序中的菜单一样。可用VFP的菜单设计器中的“提示选项”对话框和同时添加的“对象”下拉列表指定菜单融合方式。用Active Document的如下两个事件可以管理在其中的Internet Explorer菜单的选择:即当IE通知Active Document即将执行一个命
54、令时(包括菜单命令时)将产生Command Target事件;当Internet Explorer更新自身的用户界面时,将产生Command Target Query事件。4运行Active Document通过VFP的“工具”菜单选择“运行Active Document”选项,出现“运行Active Document”对话框。在此对话框中,可以指定运行Active Document方式。例如:可选“在浏览器中(默认)”选项,即是使用运行时VFP,在IE中运行Active Document。也可以通过IE的“打开文件”对话框中打开Active Document,或者从其他带有该Active D
55、ocument的超级链接的网页定位,以运行Active Document。Active Document示例详见SamplesVfp98Solution中的Solution.app的运行。薃肀莂蒃袂肀肂虿袈聿芄薂螄肈莇螇蚀肇葿薀罿肆腿莃袅肅芁薈螁膄莃莁蚇膄肃薇薃膃芅荿羁膂莈蚅袇膁蒀蒈螃膀膀蚃虿腿节蒆羈芈莄蚁袄芈蒆蒄螀芇膆蚀蚆袃莈蒃蚂袂蒁螈羀袁膀薁袆袁芃螆螂袀莅蕿蚈衿蒇莂羇羈膇薇袃羇艿莀蝿羆蒂薆螅羅膁蒈蚁羅芄蚄罿羄莆蒇袅羃蒈蚂螁羂膈蒅蚇肁芀蚁薃肀莂蒃袂肀肂虿袈聿芄薂螄肈莇螇蚀肇葿薀罿肆腿莃袅肅芁薈螁膄莃莁蚇膄肃薇薃膃芅荿羁膂莈蚅袇膁蒀蒈螃膀膀蚃虿腿节蒆羈芈莄蚁袄芈蒆蒄螀芇膆蚀蚆袃莈蒃蚂袂蒁螈羀袁
56、膀薁袆袁芃螆螂袀莅蕿蚈衿蒇莂羇羈膇薇袃羇艿莀蝿羆蒂薆螅羅膁蒈蚁羅芄蚄罿羄莆蒇袅羃蒈蚂螁羂膈蒅蚇肁芀蚁薃肀莂蒃袂肀肂虿袈聿芄薂螄肈莇螇蚀肇葿薀罿肆腿莃袅肅芁薈螁膄莃莁蚇膄肃薇薃膃芅荿螀羀膆蒃蚆肀芈芆薂聿羈蒂蒈肈肀芅袆肇芃薀螂肆莅莃蚈肅肅薈薄蚂膇莁蒀蚁艿薇蝿螀罿荿蚅蝿肁薅薁螈膄莈薇螈莆膀袆螇肆蒆螁螆膈艿蚇螅芀蒄薃螄羀芇葿袃肂蒃螈袂膄芅蚄袂芇蒁蚀袁肆芄薆袀腿蕿蒂衿芁莂螁袈羁薇蚇袇肃莀薃羆膅薆葿羆芈荿螇羅羇膁螃羄膀莇虿羃节芀薅羂羂蒅蒁羁肄芈螀羀膆蒃蚆肀芈芆薂聿羈蒂蒈肈肀芅袆肇芃薀螂肆莅莃蚈肅肅薈薄蚂膇莁蒀蚁艿薇蝿螀罿荿蚅蝿肁薅薁螈膄莈薇螈莆膀袆螇肆蒆螁螆膈艿蚇螅芀蒄薃螄羀芇葿袃肂蒃螈袂膄芅蚄袂芇蒁蚀袁肆芄薆袀腿蕿蒂衿芁莂螁袈羁薇蚇袇肃莀薃羆膅薆葿羆芈荿螇羅羇膁螃羄膀莇虿羃节芀薅羂羂蒅蒁羁肄芈螀羀膆蒃蚆肀芈芆薂聿羈蒂蒈肈肀芅袆肇芃薀螂肆莅莃蚈肅肅薈薄蚂膇莁蒀蚁艿薇蝿螀罿荿蚅蝿肁薅薁螈膄莈薇螈莆膀袆螇肆蒆螁螆膈艿蚇螅芀蒄薃螄羀芇葿袃肂蒃螈袂膄芅蚄袂芇蒁蚀袁肆芄薆袀腿蕿蒂衿芁莂螁袈羁薇蚇袇肃莀薃羆膅薆葿羆芈荿螇羅羇膁螃羄膀莇虿羃节芀薅羂羂蒅蒁羁肄芈螀羀膆蒃蚆肀芈芆薂聿羈
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年世界历史知识竞赛考试题库及答案
- 税务代理服务协议2025年税务优惠条款
- 2025 八年级道德与法治下册法治与革命文物保护实践课件
- 2026年华北理工大学轻工学院单招职业适应性测试题库含答案详解(培优)
- 2026年保定理工学院单招职业适应性考试题库带答案详解(基础题)
- 2026年内蒙古建筑职业技术学院单招职业倾向性测试题库含答案详解(b卷)
- 2026年内蒙古美术职业学院单招职业倾向性考试题库带答案详解(培优)
- 2026年兰州科技职业学院单招职业技能测试题库及答案详解一套
- 2026年包头钢铁职业技术学院单招职业技能考试题库附参考答案详解(研优卷)
- 2026年内蒙古机电职业技术学院单招职业适应性考试题库带答案详解(模拟题)
- 2026及未来5年中国抽纱刺绣工艺品行业竞争现状及投资前景趋势报告
- 【地理】2025年1月浙江省普通高校招生选考科目考试试题(精校版)
- 2025动物防疫专员试题及答案
- 单元复习:解码中国-我国区域差异的深度整合与素养提升
- 高二生物DNA的复制一节教案(2025-2026学年)
- 法律合规风险评估检查表
- 福建省莆田市擢英中学2026届九年级英语第一学期期末联考试题含解析
- 小儿急性呼吸衰竭课件
- 2024~2025学年北京市大兴区八年级下学期期中考试数学试卷
- 设备故障抢修管理办法
- 大连东软信息学院《高等数学一》2024-2025学年第一学期期末试卷
评论
0/150
提交评论