DataWindow的数据缓冲区

Posted by dohkoos on October 15th, 2009 (198 views)

在PowerBuilder中,DataWindow是用来存储和操纵数据的对象。在每个DataWindow对象中都有4个二维表作为数据缓冲区来存储数据。用户在DataWindow中对数据的操作实际上都是将数据在这几个缓冲区中进行修改和移动,最后在用户提交数据库时,系统根据这四个缓冲区中的信息形成SQL的INSERT、UPDATE、DELETE等语句。这四个缓冲区是:

Primary Buffer
这个缓冲区是存放填充窗口中DataWindow控件的数据的,调用DataWindow控件的Retrieve()函数和InsertRow()函数可以将数据填入这个缓冲区中。当使用有关DataWindow删除和过滤函数时,相应记录将从这一缓冲区中删除。而在执行DataWindow的Update()函数时,PowerBuilder将查看这一缓冲区中的记录以形成INSERT和UPDATE语句。

Delete Buffer
这个缓冲区保存的是用DeleteRow()函数从Primary Buffer中删除的记录,执行Update()函数时,系统根据这一缓冲区的记录形成DELETE语句。

Filter Buffer
这个缓冲区存储的是从Original Buffer使用Filter()函数过滤到Primary Buffer中后剩余的记录。

Original Buffer
这一缓冲区存储的是DataWindow最初执行Retrieve()函数时得到的全部记录。当提交数据库时,根据Primary Buffer生成的UPDATE语句和根据Delete Buffer生成的DELETE语句都要依据这一缓冲区来构造这些SQL语句中的WHERE子句。

Original Buffer由PowerBuilder内部维护,PowerBuilder所提供的任何函数都无法改变它的值,不过通过PowerBuilder所提供的GetItem系列函数可以读出DataWindow最初从数据库中查到的原始值。通过这些函数我们可以编程实现所谓的Undo功能,并且得到在使用乐观锁时形成提交数据库的WHERE子句。如果您当前使用的DataWindow没有设置修改的权力,您将不能对Delete Buffer和Original Buffer进行操作,而且当调用Update()时也将引起系统错误。

数据缓冲区的状态值
Primary Buffer和Delete Buffer都有行级和列级的状态值,这个状态值是一个枚举类型。在提交时由该行的状态值来决定是否要产生SQL语句,其中Primary Buffer产生的是INSERT和UPDATE语句,而Delete Buffer产生的是DELETE语句。我们用GetItemStatus()函数和SetItemStatus()函数可以对这一状态值进行操纵。这一枚举状态有以下四种:

NotModified! ——— 指定单元的数据和原始数据相同,没有发生改变。
DataModified! ——— 指定单元的数据和原始数据不同,发生了改变。
New! ——— 该数据行是新增加的,但数据没有发生改变(数据为空或缺省值)。
NewModified! ——— 该数据行是新增加的,且数据已发生改变(用户键盘输入或调用SetItem()函数)。

在上面的这四个值中,NotModifed!和DataModified!可以表示行和列的状态,而New!和NewModified!只可以表示行的状态。

让我们来看下面这一实例:
我们有这样一张表,表中有三个字段,其中ITEM是主键。
ITEM CHAR(5)
NAME CHAR(20)
QUANTITY INT

在script中我们查询这张表的记录,得到以下的这些信息存储在Primary Buffer和Origianal Buffer中。
dwbuffer-1

在窗口中,我们编程过滤掉数量为0的行,并且加上一个空行:
dw_1.SetFilter("quantity=0")
dw_1.Filter()
dw_1.InsertRow()

这时Primary Buffer的状态为:
dwbuffer-2

在Filter Buffer中的记录为:
dwbuffer-3

用户在新插入行中输入数据,删除了第3行数据,并修改了第2行数据。当他离开这个DataWindow时,Primary Buffer和Delete Buffer的状态如下:
dwbuffer-4

dwbuffer-5

这时执行dw_1.Update()函数,系统将基于这两个缓冲区生成SQL语句。
dwbuffer-6

在Primary Buffer中,状态为NotModified!和New!的行将被忽略而不产生SQL语句。状态为DataModified!的行将产生UPDATE语句,状态为NewModified!的行将产生INSERT语句,在Delete Buffer中的行将产生DELETE语句。使用DataWindow的Reset()函数和Retrieve()函数以及改变DataObject属性时,系统将重置这几个缓冲区。

Related Posts

如何设置数据窗口中某行某列的背景颜色

Posted by dohkoos on October 18th, 2008 (555 views)

假设数据窗口有n行数据,在修改某个column的数据后希望能将该column的背景色变成红色,代码该如何写呢?

要对某行某列的属性进行更改,可以使用modify函数。在对某行某列的属性进行改变时,你需要先判断当前行是否是被修改数据的那行,如果知道行号的话(例如在itemchanged事件中),你可以使用下面的代码

dw_main.modify(ls_colname + "background.color = '0~tIf(getrow() = " + string(row) + ", 255, 16777215)'")

当然,你也可以这么写

dw_main.modify(ls_colname + "background.color = '0~tIf(getrow() = currentrow(), 255, 16777215)'")

Related Posts

PowerBuilder如何调用默认的邮件客户端

Posted by dohkoos on September 20th, 2007 (393 views)

在某个窗口上有一个文字超链接(StaticHyperLink控件),点击后就打开默认的邮件客户端,并且把指定收件人的邮件地址填写到收件人地址栏中。

如果在StaticHyperLink控件的URL中使用mailto协议,的确能够做到上述的要求。但是有个问题是在打开邮件客户端前总是先打开一个IE窗口,这样使得用户的体验非常差。而PowerBuilder自带的mailsession对象则只能调用outlook express,根本就不用考虑。

google之后发现可以通过调用外部函数ShellExecute来解决这个问题。首先在Global/Local External Functions中添加如下声明:
function ulong ShellExecuteA(ulong hwnd, &
                            string lpOperation, &
                            string lpFile, &
                            string lpParameters, &
                            string lpDirectory, &
                            long nShowCmd) library "shell32"

然后在StaticHyperLink控件的Clicked事件中添加代码
string ls_null

SetNull(ls_null)
ShellExecuteA(Handle(parent), &
            "open", &
            "mailto:sample@anonymous.com", &
            ls_null, &
            ls_null, &
            1)    // SW_SHOWNORMAL

请注意4个string类型的参数,一定是string xxx,千万不要使用下面这种声明方式:
function ulong ShellExecuteA(ulong hwnd, &
                             ref string lpOperation, &
                             ref string lpFile, &
                             ref string lpParameters, &
                             ref string lpDirectory, &
                             long nShowCmd) library "shell32"

刚开始的时候我就使用了这种声明方式,结果每次程序执行到ShellExecuteA时都会弹出一个异常对话框,搞的我非常郁闷。

Related Posts

People who read this, also read...

数据窗口中Column控件的editmask.useformat属性的作用

Posted by dohkoos on September 11th, 2007 (378 views)

当数据窗口中的editmask控件失去焦点时,如果editmask.useformat为yes,则使用format属性值格式化editmask的内容,否则,使用editmask.mask属性值格式化控件的内容。当editmask得到焦点时,使用editmask.mask格式化内容。

// 伪代码
if (isfocused) {
    editmask.mask
} else if (losefocus) {
    if (editmask.useformat == "yes" && format != "") {
        format
    } else {
        editmask.mask
    }
}

Painter: Use Format option

Related Posts

People who read this, also read...

[PB2J]PowerBuilder标识符 versus Java标识符

Posted by dohkoos on December 13th, 2006 (338 views)

在使用减号(-)、负号(-)、减1(--)运算符时,必须在这些符号的前面加上空格,原因在于PowerBuilder会把这些符号当成标识符的一部分。

PowerBuilder Java
必须以字母或下划线(_)开头 必须以字母、下划线(_)或美元符号($)开头
其余字符可以是字母、数字、下划线(_)、美元符号($)、
短横线(-)、号码符号(#),百分号(%)
其余字符可以是字母、数字、下划线(_)、美元符号($)
最长40个字符(实际最大长度可达99个),中间不能有空格 未规定最大长度,中间不允许有空格
不区分大小写 区分大小写

问题:如何禁止在标志符中使用短横线(-)?
可以在PB.INI的[pb]节中将DashesInIdentifiers=1修改为DashesInIdentifiers=0

Related Posts

People who read this, also read...