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



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

2013-04-12 17:29:44|  分类: PB编程 |  标签:pb  dw  数据窗口   |举报 |字号 订阅

下载LOFTER客户端

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

 

1--缓冲区的介绍

 

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

 

在每一个DataWindow对象中有4个二维表作为数据缓冲区,用来存储查询到的数据。用户在DataWindow中对数据处理系统内部的操作实际上都是将数据在这几个缓冲区中进行的修改和移动,最后在用户提交数据库时,系统根据这四个缓冲区中的信息形成SQL的IN-SERT,UPDATE,DELETE等语句。

 

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

 

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()时,就不会对后台数据库有影响。

----如果您对当前使用的DataWindow没有设置修改的权力,您将不能对Delete缓冲区和Original缓冲进行操作,而且当调用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是目标数据窗口控件名称,可以是与dwcontrol相同的数据窗口控件,也可以是不同的数据窗口控件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()函数,也可能是由于它的某列具有缺省值,本状态只适用于行,不适用于单个列。

insertrow后,具有默认值的行,是什么状态?

 

数据窗口中行或列的修改状态决定Update()函数将为该行或该列产生何种类型的SQL语句。

  • 对主缓冲区和过滤缓冲区中的行,状态为NotModifiedNew!的行将被忽略而不产生SQL语句,状态是NewModified!的行产生Insert语句;状态是DataModified!的行产生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给出了这种限制

 

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!,然后再改成NotModified!状态

 

 

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

 

 

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

 

 

  dw_control.retrieve()之后,主缓冲区、过滤缓冲区中和原始缓冲区中状态是?

使用DataWindowReset()函数和Retrieve()函数以及改变DataObject属性时,系统将重置这几个缓冲区。

当用户插入一个新行时,编程者往往要自动在新插入行中的某些列中插入一些缺省的数据值。这时,用户并没有对数据作任何修改。可是在用户要关闭这一窗口时,如果在CloseQuery事件中用ModifiedCount()函数查看数据是否修改,得到的结果显然是有所改变。用户将得到一个提示信息框:"是否打算保存所作的修改?//取消"——这显然是不适合的:而且如果用户选择的是保存时,这些原应是空记录的行也成为了有内容的行,系统将其形成SQLINSERT语句提交数据库,这样的结果更为恶劣。为改变这一状况,我们可以用SetItemStatus()函数将该行的状态改为New!。即当有新行插入并且设置了缺省值之后,置该行的状态值为New!。下面的程序就可以得到如上的功能。

Insertanewrowindw_1

Long l_Row

l_Row=dw_1.InsertRow(dw_1,GetRow())

dw_1.SetItem(l_Row,"discount_pct",0,10)

---SetthrowstatustoNew!sothattheCloseQuerycheckwillonlydetectuserentries.

dw_1.SetItemStatus(l_Row,0,Primary!,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


Updates the database with the changes made in a DataWindow control or DataStore. Update can also call AcceptText for the current row and column before it updates the database.
integer dwcontrol.Update ( { boolean accept {, boolean resetflag } } )
accept true-update之前执行accepttext操作,并且如果the data fails validation,update操作将取消
 false-不执行accepttext操作
resetflag 是否允许dwcontrol自动reset the update flags

 

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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值