请教一个问题.三层应用中服务器数据交互问题.

lingdove 2010-10-03 10:23:25
从服务器端得到数据后,在客户端修改后更新.

程序大概过程为,服务器端检索数据后,用SAVEAS函数存为本地文件,处理后发送给客户端,客户端数据窗口用importfile导入,设置数据窗口resetupdate (这里这样处理不知道对不对,如果不RESETUPDATE,呆会就是保存的时候就是插入数据而且不是更新数据了),保存的时候用getchange取出BLOB,传送到服务器后用setchange(BLOB)保存.

运行的时候经常第一次可以修改,操作窗口多几次,偶尔会出现错误.提示rows changed between retrieve and update.

不知道是哪一个步骤处理不对?还是IMPORTFILE后UPDATE的问题?


?????????????
...全文
250 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhangyiteng 2010-10-19
  • 打赏
  • 举报
回复
楼主有问题可以加群:122879526
互相交流学习
zhangyiteng 2010-10-19
  • 打赏
  • 举报
回复
一种情况是:提交后更改(但目标数据窗口不要做任何修改)
//提交
if gnv_eas.f_buss(ls_buscd, dw_detail,ls_id)<0 then
return
else
// dw_detail.SetItemStatus(1,0,primary!,NotModified!)
dw_detail.resetupdate( )
end if
二种情况:你先检索的数据无效了。你从新提取后要给原失效数据窗口赋值并希望它变成刚检索状态。
if dw_detail.rowcount( )>0 then
//将新行的修改状态置为NotModified!
gf_setdwrowstatus(dw_detail, NotModified!, 1, 1)
end if
gf_setdwrowstatus代码如下:

//////////////////////////////////////////////////////////////////////////////
//
// 函数名: gf_setdwrowstatus
//
// 访问权: public
//
// 参数:
// adw_require 需要设置的DataWindow
// adw_newstatus 需要设置行的新状态
// al_startrow 开始行
// al_endrow 结束行
//
// 返回值: boolean
// TRUE 成功设置
// FALSE 没有设置成功
//
// 描述: 设置DataWindow指定开始行到结束行的行状态
//
//////////////////////////////////////////////////////////////////////////////
//
// 修正历史
// 最初版本(张艺腾)
//
//////////////////////////////////////////////////////////////////////////////
Long lRow
dwItemStatus dwStatus

If al_startrow > al_endrow Then
lrow = al_endrow
al_endrow = al_startrow
al_startrow = lrow
End If

For lrow = al_startrow To al_endrow
dwStatus = adw_require.GetItemStatus(lrow, 0, Primary!)
Choose Case adw_newstatus
Case New!
Choose Case dwstatus
case NewModified!, DataModified!
adw_require.SetItemStatus(lrow, 0, Primary!, NotModified!)
adw_require.SetItemStatus(lrow, 0, Primary!, New!)
Case NotModified!
adw_require.SetItemStatus(lrow, 0, Primary!, New!)
End Choose
Case NewModified!
Choose Case dwstatus
case New!, DataModified!, NotModified!
adw_require.SetItemStatus(lrow, 0, Primary!, NewModified!)
End Choose
Case DataModified!
Choose Case dwstatus
Case New!, NewModified!, NotModified!
adw_require.SetItemStatus(lrow, 0, Primary!, DataModified!)
End Choose
Case NotModified!
Choose Case dwStatus
Case New!, NewModified!
adw_require.SetItemStatus(lrow, 0, Primary!, DataModified!)
adw_require.SetItemStatus(lrow, 0, Primary!, NotModified!)
Case DataMOdified!
adw_require.SetItemStatus(lrow, 0, Primary!, NotModified!)
End Choose
End Choose
Next
Return True

//掉用例子
//If lower(istr_recordmanager.a_retrieveparm1) = 'edit' Then
// //说明需要修改
// //将原dataWindow的当前行copy到现在的DataWindow中
// If istr_recordmanager.dw_desc.RowsCopy(istr_recordmanager.dw_desc.GetRow(), &
// istr_recordmanager.dw_desc.GetRow(), &
// Primary!, dw_maint, 1, Primary!) <> 1 Then
// Messagebox("错误", "拷贝记录出错,请通知系统管理员!")
// Else
// gf_setdwrowstatus(dw_maint, NotModified!, 1, 1)
// dw_maint.Event rowfocuschanged(1)
//
// End If
//Else
// dw_maint.Event pfc_insertrow()
//End If

2sword 2010-10-12
  • 打赏
  • 举报
回复
磅学习。
yuanp2001 2010-10-08
  • 打赏
  • 举报
回复
可以用视图来写!
lingdove 2010-10-07
  • 打赏
  • 举报
回复
主要是考虑速度问题,现在已经处理好了,速度可以提高1/3以上.
这个功能主要用于查询数据,其它方面的还得按原来的方式走.

确实是不会一致,自动增长的列,UPDATE之后没有数据出来的.
但是如果我用get/setfullstate等来进行操作,也是一样不会出来的.如果要它出来,必须再重新获取一次.
mz_jenny 2010-10-06
  • 打赏
  • 举报
回复
我有点搞不明白 人家写好的东西你不用 非得自己整一个复杂的 还很多限制 不稳定的东西 搞不好你的东西搞好20M宽带已经出来了

我对resetupdate就一致了 有不同看法 其实数据窗口自动增长列 update 后 客户端resetupdate怎么会一致



WorldMobile 2010-10-06
  • 打赏
  • 举报
回复
savaas不好用,使用getfullstats ,setfullstats, getchanged, setchanged这几个函数来实现
lingdove 2010-10-06
  • 打赏
  • 举报
回复
saveas这种方法坛里也有兄弟用这样子处理,如果是新增数据,它就传数据,如果是更新的,它就传整个BLOB.

这个问题我找到原因了,是因为数据窗口设计的时候,empty string is null没有勾上.
第一次UPDATE的时候,它存到数据库里面是空字符(不是NULL),再UPDATE的时候,那条UPDATE语句为:
UPDATE BIAO SET A='AAA' WHERE B is null and A='BBB'
这个条件在数据库表里检索不到数据的,因为B不是NULL,而是空串.晕死了,一个问题搞了几天.
谢谢大家.
dawugui 2010-10-04
  • 打赏
  • 举报
回复
不明白你的做法.
一般是客户端去获取服务器的数据,然后做相关操作即可.不明白为什么你需要从服务器绕那么大的弯子将数据传给客户端?

帮顶.
wag_enu 2010-10-04
  • 打赏
  • 举报
回复
三层结构C/S 的C 和中间S 的数据交互大至是用getfullstats ,setfullstats, getchanged, setchanged, 这几个方法完成的。

C端需要的数据第一次从中间S 获取的时候要用getfullstats 取blob后传给C, C用setfullstats。
然后回传。。。
但是你用saveas 成文件再传会影响DW的update 状态的。
lingdove 2010-10-04
  • 打赏
  • 举报
回复
楼上你可能弄混了,setchange只是将数据窗口需要修改部份设置到数据窗口中,并不是复制整个数据,复制整个数据是用setfullstate.
lingdove 2010-10-04
  • 打赏
  • 举报
回复
我分析过了,getchange跟GetSQLPreview()原理一样,只是取需要修改的部份,所以数据量很小的.
一个几千条记录的数据窗口,如果你只改几条记录的值,getchange取出来的数据只有几百BYTE左右.其实就是几条SQL语句,标明哪些数据需要提到服务器去修改.如果服务器端setchange后update成功,客户端再resetupdate一下,两端就一致了.getchange提交上去的数据里面不含status的,在getchange的时候,数据窗口已经自动分析过status了.

所以还存在一种情况,如果你送到服务器端的数据窗口内容,服务器端中间件还需要根据这个数据窗口的各种状态来处理数据后再提交数据库的话,则必须用getfullstate/setfullstate了.
fang3307 2010-10-04
  • 打赏
  • 举报
回复
留下记号,我也有类似疑问
glint 2010-10-04
  • 打赏
  • 举报
回复
或者不用getchange、setchange(BLOB)这种方式,这2函数没准有点不适合这种场景,服务器端setchange(BLOB)的那个DW已经不是原来那个了吧,你应该不会把刚开始retrieve的那个DW还保存在服务器内存中,改成拷贝修改过或者新增的行道另一个datastore中并设置每行的setitemstatus为原DW中的状态,然后datastore.getfullstate后传送到服务器。当然要是有并发问题,直接UPDATE还是会出来rows changed between retrieve and update,不过你还可以在服务器上运行GetSQLPreview()来处理,更新需要更新的,跳过已经被修改的数据
glint 2010-10-04
  • 打赏
  • 举报
回复
既然这样,保存的时候也不要用getchange取出BLOB,再传送到服务器后用setchange(BLOB)保存这种方式,这样传送的数据量还是比较大,何不用GetSQLPreview()获取更新的SQL语句压缩后传送到服务器处理?GetSQLPreview()获取的SQL语句压缩率会比较大,因为包含大量重复的字符串
sjlion 2010-10-04
  • 打赏
  • 举报
回复
兄弟,那要看你是正确性优先还是效率优先。用fullstate就是为了保证服务器端和客户端的完全一致,否则可能会在数据的完整性和一致性上出现问题。就你的方法而言,如果你对并发控制要求不是很严格的话,Where Clause for Update/Delete”中用Key Columns应该没问题。否则的话你恐怕要在服务器端跟踪下SQL,找到具体的原因才行了。
smitxx 2010-10-04
  • 打赏
  • 举报
回复
一般在客户机在处理这些数据的时候会有一个多用户使用共享的数据冲突,不知道是不是这个问题
lingdove 2010-10-04
  • 打赏
  • 举报
回复
getfullstate和saveas处理起来数据量差异很大,不要只是相信网上所说的PB处理三层一定要用getfullstate等函数,getfullstate连语法,各缓冲区数据,各个数据状态等等都会获取(下拉数据窗口好像不会获取).用saveas取得数据后,在客户端处理后,再用getchange发送到服务器端更新即可.getchange不会获取所有数据的,只传送部份修改数据,数据量也是非常小的,再加上两端压缩/解压缩,处理起来的速度可以大大提高.我测试过,7000条记录的数据窗口,getfullstate后压缩大约为313K,saveas后压缩大约为190k,相差1/3,如果只是一条记录(10个字段),getfullstate为6K左右.saveas大约为几百个字节,两者区别很大.
lingdove 2010-10-04
  • 打赏
  • 举报
回复
可以测试一下,用getfullstate等函数传送数据,数据量比saveas获取数据后的差异,我的一个表7000条数据,用getfullstate取数据为313K(压缩后),用saveas取数据为190K(压缩后)左右,能省1/3的数据量(这正是三层开发的重点,减少与服务器端的交互和数据传送).数据量在100条以内的,用第一种方法经常要6-8K左右,用第二种方法大概为1-2K左右.当然主要还要看表里面的字段,但是已经有非明显的区别,这也是为什么我想采用SAVEAS和IMPORTFILE来处理数据的理由.当然这种方式仅能用于数据检索,如果在中间层有对数据窗口进行数据处理的返回,则应该使用getfullstate来处理.
服务器3MADSL,客户端2M ADSL,同一城市,如果操作一些常用数据,用第二种方法处理的话,感觉不到明显停顿.
sjlion 2010-10-04
  • 打赏
  • 举报
回复
嗯,楼上说的对。不要用saveas,getfullstate,压缩后传送,setfullstate,getchanged,再压缩后回传
加载更多回复(3)

662

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder Web 应用
社区管理员
  • Web 应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧