PB-数据窗口缓冲区与数据修改状态

来源:互联网 发布:php防止重复提交 编辑:程序博客网 时间:2024/04/29 02:39

PB-数据窗口缓冲区与数据修改状态

 

1--缓冲区的介绍

 

在应用程序运行时,用户对数据窗口进行的操作情况是很复杂的,删除、插入、修改等操作有可能都会发生。记录哪些数据修改过、哪些数据需要删除、哪些数据是新增加的等等,都是很重要的工作,以便数据保存时能够正确修改数据库。这些工作都是由数据窗口缓冲区来完成的。

 

数据窗口在运行时要创建四个缓冲区,分别是主缓冲区、删除缓冲区、过滤缓冲区和原始缓冲区,这四个缓冲区各司其职、共同配合,来保证数据窗口对数据的正确处理。下面分别加以介绍。

 

1主缓冲区[Primary Buffer]--存放检索出来的数据,但不包括过滤掉和删除掉的数据。

最重要的一个缓冲区,保存的是当前显示在数据窗口中的所有数据以及它们的修改状态,函数中的缓冲区参数缺省也是该缓冲区,这个缓冲区是存放填充窗口中DataWindow控件中数据的,调用DataWindowRetrieve()函数和InsertRow()函数可以将数据填入这个缓冲区中。当使用有关DataWindow删除和过滤函数时,相应记录将从这一缓冲区中删除。而在执行DataWindowUpdate()函数时,PowerBuilder将查看这一缓冲区中的记录,以形成SQL INSERTUPDATE语句。

2删除缓冲区[Delete Buffer]--存放从主缓冲区中删除掉的数据。

该缓冲区保存的是用DeleteRow()或者dw_1.rowsmove(1,3,primary!,dw_1,1,delete!)函数从Primary Buffer中删除的记录,执行Update()函数时,系统根据这一缓冲区的记录形成DELETE语句。在数据没有提交到数据库之前,可以从该缓冲区中将数据恢复出来,数据提交后,该缓冲区中的数据清空。

3过滤缓冲区[Filter Buffer]--存放从主缓冲区中过滤掉的数据。

该缓冲区中保存的是没有通过【过滤条件】的所有数据,这些数据在存储时同主缓冲区的数据一起生成相应的insertupdate语句。存储的是从Original Buffer使用Filter()函数过滤到Primary Buffer中后剩余的记录。

4原始缓冲区[Original Buffer]--存放从数据库里检索到的原始数据。

这一缓冲区存储的是DataWindow最初执行retrieve()函数时得到的全部记录。当提交数据库时,根据Primary Buffer生成的UPDATE语句和根据Delete Buffer生成的DELETE语句都要依据这一缓冲区来构造这些SQL语句中的Where子句。它由PowerBuilder内部维护,PB所提供的任何函数都无法改变它的值,不过通过PowerBuilder所提供的GetItemX系列的函数可以读出DataWindow最初从数据库中查到的原始值。通过这些函数我们可以编程实现所谓的“Undo”功能,并且得到在使用乐观锁时形成提交数据库的WHERE子句。如下:

 

String LName,LName1

LName = dw_2.GetItemString(1, "name", Primary!, TRUE)原始缓冲区数据

LName1 = dw_2.GetItemString(1, "name", Primary!, false) 修改后的主缓冲区数据

 

或用 点状表示法

 

LName=string(dw_top.object.name.ORIGINAL[1])原始缓冲区数据    

 

修改后的主缓冲区数据

LName1=string(dw_top.object.name.Primary[1])string(dw_top.object.name.CURRENT[1])

 

综上所述,不管我们对缓冲区数据做任何处理,只要没有执行UPDATE()时,就不会对后台数据库有影响。

 

2--数据缓冲区的状态值

 

1,所有这些数据的移送无需脚本的干预,只管使用相应的函数即可。

 

日常使用中很多数据窗口函数经常对这四个缓冲区进行操作【original缓冲区在脚本中很少使用】,默认缺省的缓冲区为Primary!。这三个[original除外]缓冲区,除了保存相应的数据外,都自动维护这些数据的修改标志,它们之间的协作也是自动维护的。例如,当使用过滤函数时,没有通过过滤条件的数据自动从Primary缓存区移送到Filter缓存区;执行删除操作时,数据自动从Primary缓存区移送到Delete缓存区。

 

2,一些特殊情况下需要人工干预,特别是在需要数据恢复时。

 

经常使用的方法是,专门建立一个数据窗口用来显示缓冲区的数据,使用函数RowMove,它可以将数据从一个缓冲区移动到另外缓冲区中,在两个数据窗口之间移动数据。该函数的语法是:

dwcontrol.RowsMove ( startrow, endrow, movebuffer, targetdw, beforerow,targetbuffer )

其中,dwcontrol是进行移动操作的源数据窗口;startrowendrow是要移动数据的范围(包括这两个行号的数据);movebuffer指要从哪个缓存区移出数据,可以是Primary!、Delete!Filtertargetdw是目标数据窗口控件名称;beforerow表示在目标数据窗口的哪一行之前插入移入的数据,如果该数值比目标数据窗口的行数大,则在最后插入移入的数据;targetbuffer是目标缓存区,取值同movebuffer一样。

 

dw_1.rowsmove(1,3,primary!,dw_1,1,delete!)//将要删除的行 移动到 删除缓冲区 然后再UPDATE

dw_cur.RowsMove(dw_cur.GetRow(),dw_cur.GetRow(),Primary!,dw_del,dw_del.RowCount() + 1,Primary!)

 

3,另外一种情况是直接修改缓冲区数据修改标识

 

行与列的修改状态在PowerBuilder中为dwItemStatus枚举类型值,使用函数dwcontrol.GetItemStatus ( row, column, Primary! )可以获取该缓冲区内指定单元的状态,当参数column0时,表示读取整个列的修改状态。有以下状态。

NotModified! :指定行或列处的数据和原始数据相同,没有修改过。

DataModified!:指定行或列处的数据和原始数据不同,修改过。

New!:该数据行是新增加的,但还没有在该行上输入数据,只适用于行,不适用于单个列。

NewModified!:该数据行是新增加的,并且已经在该行上录入了数据,改变是通过用户键盘输入或SetItem()函数,也可能是由于它的某列具有缺省值,本状态只适用于行,不适用于单个列。

 

数据窗口中行或列的修改状态决定Update()函数将为该行或该列产生何种类型的SQL语句。对主缓冲区和过滤缓冲区中的行,Update为状态是NewModified!的行产生Insert语句,为状态是DateModified!的行产生Update语句,只有状态是DataModified!的列才会包含在Update语句中。对删除缓冲区中的行,若其状态是New!NewModified!,则Update语句不会为其产生Update语句。

 

这些修改标识都是由数据窗口自动维护的,一般情况下没有必要编写脚本修改这些标记,但并不是说就不能修改。PowerBuilder提供了函数SetItemStatus,它的语法是:

dwcontrol.SetItemStatus ( row, column, dwbuffer, status )

其中,row参数指定将要修改状态的行;column参数指定将要修改状态的列(可以是整型的列号,也可以是string类型的列名),当列号为0时表示要修改row指定的整行的状态;dwbuffer指定要修改哪个缓冲区(肯定不能是original),status为上面的四个取值中的一个,但不是任意的取值,因为有些状态不能用该函数设置成另外一种状态,必须是能够转换的状态。对于如何改变状态,PowerBuilder有一些限制,表1给出了这种限制,其中Yes表示可把初始状态改变为指定状态,No则表示不可以。

 

1数据修改状态设置约束

初始状态

指定状态

New!

NewModified!

DataModified!

NotModified!

New!

——

Yes

Yes

No

NewModified!

No

——

Yes

New!

DataModified!

NewModified!

Yes

——

Yes

NotModified!

Yes

Yes

Yes

——

 

 

表中的Yes表示可以使用SetItemStatus进行该状态设置,No表示不会产生预期的状态,如果标明了某个特定的状态,则说明是新的状态,而不是期望的状态。例如,数据窗口dw_1的第1行第1列的当前状态为DataModified!,使用函数dw_1.SetItemStatus(1,1,New!)后,第1行第1列的状态改变为NewModified!。同样对于该数据窗口dw_1,如果使用函数dw_1.SetItemStatus(1,1,NotModified!),则会将其状态改变为NotModified!。当从一种状态不允许转变到另一种状态时,可以修改成其他一个中间状态,然后再进行一次转换。例如,要从new!改成NotModified,应该首先转换到DataModified!

 

  利用函数RowsCopyRowsMove可以在不同DataWindow控件(DataStore对象)之间或同一DataWindow控件(DataStore对象)的不同缓冲区之间复制、移动数据行。

 

 

  当某行在删除缓冲区中时,或者在主缓冲区或过滤缓冲区中,并且状态为NewModified!DataModified!时,其更新标志被设置。函数dw_control.ResetUpdate()清除DataWindowDataStore中主缓冲区和过滤缓冲区中的更新标志并清空其删除缓冲区。清除更新标志后,所有行的状态为NotModified!New!

 

3--应用举例

 

(1)在数据窗口中,某些列常具有缺省值,或我们在执行了InsertRow操作后立即使用SetItem函数为某些列赋值。如果用户执行了一个插入操作后立即关闭窗口会触发closequery事件,这时会提示用户记录已经被修改,但用户并没有感觉到对数据的修改。为避免出现这种情况,可作如下处理:

 

  intli_new_row

  li_new_rowdw_l.InsertRow(0)

  //通过SetItem函数为列赋值

  dw_l.SetItem(……)

  //将新行的修改状态置为NotModified!

  dw_l.SetItemStatus(li_new_row,0,primary!,NotModified!)

 

(2)在应用程序中提供Undo功能,将实现很好的用户友好效果。本例中将数据窗口dw_l中的当前行、当前列的显示值置为从数据库中检索出的原始值:

  string ls_ori_val

     ls_ori_valdw_l.GetItemString(dw_l.GetRow(),dw_l.GetColumn(),Primary!,True)

     dw_l.SetText(ls_ori_val)

 

(3)在协调两个DataWindow对象dw_ldw_2的更新时,若其中一个更新失败,应阻止重设更新标志,以便回滚事务,一旦所有数据窗口都已成功更新,就可使用COMMIT结束该事务,并使用ReSetUpdate重新设置数据窗口的状态标志。

  Int li_ret_code

  li_ret_codedw_l.Update(True,False)//阻止重设更新标志

  If li_ret_codel then

    li_ret_codedw_2.Update(True,False)//阻止重设更新标志

    lf li_ret_codel then

      dw_l.ResetUpdate()//清除更新标志

      dw_2.ResetUpdate()//清除更新标志

      COMMIT

    Else

       ROLLBACK;

    Endif

  Endif

(4)将数据行从删除缓冲区移到主缓冲区,实现取消删除的功能。

     dw_l.RowsMove(l,dw_l.DeletedCount(),Delete!,dw_l,l,Primary!)

 

原创粉丝点击