关于三层数据提交的问题(300分)(100分)

W

wxkabc

Unregistered / Unconfirmed
GUEST, unregistred user!
我所作的三层服务器是采用Socket连接的(后台数据库是Oracl),
其功能已近完善。只是在最近的测试中发现存在提交数据失败的
现象,根据本人的跟踪调试发现数据提交不上去的存在一定的规
律性。
其规律如下:
当在客户端修改字符串型字段的数据时,把其值清空(假设原来
有值)保存正常,之后再修改该字段值提交则发生如下错误:
Record not found or changed by another user
如果不将其值清空而是直接输入另一字符串则不会出现上述问题。
请各位高手赐教:发生上述问题的原因是什么?如何解决?
 
进行数据更新的数据集组件(或ClientDataSet连接的DataSetProvider组件,要看你的程序而定)
的UpdateMode改为upWhereKeyOnly
这是数据库中主键设置不正确所至,或者是其它原因,不过要看整个数据库的结构才知道。
 
首先谢谢szf的回答。
对于将UpdateMode改为upWhereKeyOnly
我也试过,但总是提交失败,是否还得设置其它属性,还望赐教。
其它两种UpdateMode我都试过,对于我的问题它们没有什么区别。
对于表的结构我想影响不大,因为我们做的系统有几百个表,凡我
测试过的表都存在此问题。
 
我也碰到类似的问题,也出现Record not found or changed by another user
后来发现是表的字段名问题,我用的是ACCESS2000
 
Record not found or changed by another user
我告诉您解决方法,您在保存数据后,再取一次数据,再修改,如果保存后,一定要再取
一次数据。否则要出错,保存----取数据---修改----保存---取数据。。。。。
OK
 
注意:我也遇到过该问题,解决方法如下:
1.将UpdateMode改为upWhereKeyOnly
2.用midas.dll 7.0(delphi7自带,用Regsvr32 注册)
OK!(我刚解决3天!^_^。主要原因还是midas.dll版本太低,功能受限制!)
 
谢谢各位的建议!
对于 juanZ 的所说的我想不大可能,因为我用的几百个表不可能都是字段名的问题。
对于 billrobin 的提议,我也认为不可行。我们做的MIS的数据量比较大
如果这样做的话会大影响系统的效率。
对于 zhongtu,的第一种方法上面我已经提过。第二种方法我的同事也试过,好象也
不行,是否有其它应该注意的地方请指点。
谢谢大家!
 
这个bug从以前就有,如果你将字段值设置为允许为空就可以,但是这无助于问题的解决.
根本的办法就是在提交前进行检查,如果发现是空的就滤掉它.我就是这样解决的,但是
你使用的是数据库控件,又是三层的,非常麻烦.
 
billrobin的方法是对的。
通过SQLMonitor观察,发现如果如楼主的做法,则第二次update操作时,BDE产生的
sql语句是 where DataField='',而再重新打开ClientDataSet后进行update时,BDE产生的
sql语名是 where DataField is null
Oracle把''保存到数据库时自动变成null,所以上面的where DataField=''不能更新任何数据,
就报"Record not found or changed by another user"了。
另一个解决办法是
把DataSetProvider的ResolveToDataSet设置为True,对应的TQuery组件的RequestLive为True
就没有这个问题了。
但通过SQL-Monitor观察,发现在客户端程序ApplyUpdates时,应用服务器的做法也是重新
select一次数据,然后再update数据的。
至于哪种方法速度快,可以测试一下再决定了。
不过第二种方法对客户端程序来说是透明的,编程时不用考虑太多后台的事情。而且重新
select的数据只在oracle和appserver之间流动,估计会比第一种方法快。
 
我知道billrobin的方法是对的,但在数据量大的情况会影响一定的速度。
我分析出现"Record not found or changed by another user" 问题的原
因与你所说的一样。
对于您所说的第二种方法,我们用的是ADO,所以不存在RequestLive的设置
问题。而我们的应用服务器也是先Select数据然后再ApplyUpdates提交。
 
使用ADO就更简单了,只要把DataSetProvider的ResolveToDataSet设置为True就可以,
连字段名的大小写都不用考虑。
反而用默认的False好象更新不了数据,不知是不是用了缓冲池有关。你那里是怎么样的?
 
我这里是使用了缓冲池,但我认为与它无关。我认为你前面说的比较正确
是Oracle把''保存到数据库时自动变成null,而客户端的值为'',所以再
次提交时就会发生“Record not found or changed by another user”。
但我不知除重新打开数据集外是否有其它方法能解决此问题?
谢谢你的支持‘szf’。
 
在我这里没有问题,也是用了缓冲池(Demo/midas/pooler范例改写的),
只修改了DataSetProvider的ResolveToDataSet的设置为True就一切OK了。
按你的"规律"来操作,一点儿问题也没有。
我不知道你有没有按我说的方法来做。
 
我认为是客户端的数据不能刷新的问题,因为我的服务器是
不保留状态的,而提交则是自己写的方法把数据包发到服务
器上进行提交,这样在保存后再对客户端进行刷新。可能是
我处理有问题,我试了直接用ApplyUpdates提交是没什么问
题。
 
反过来说,您用的ApplyUpdates并不是完全意义上的三层。我曾经见过一个十分稳定的三层
。基本上不用ApplyUpdates。全由SQL在中间层完成。我遇到过您的问题。实际上取数据并
不是要花多少时间。我试过。或者,您改一下BDE的参数。INIT。
 
前提:
1.DataSetProvider的ResolveToDataSe
其连接的Query的Requestlive为True
2.更新表不要有SN(自增字段)
3.日期字段不要用默认值
方法:(注意,1--2是步骤,不是两种方法)
1.将UpdateMode改为upWhereKeyOnly
2.用midas.dll 7.0(delphi7自带,用Regsvr32 注册)
我已成功,此问题困扰我一个多星期!
但对自增字段来说,我只能用SQL语句
 
我也遇到过同样的问题,我也采用了midas.dll 7.0,可是还是不行,请楼上给出详细的
实施办法好嘛?
我现在的解决办法是全部采用SQL语句来提交记录,在客户端自动产生INSERT/UPDATE的SQL
语句,传到应用服务器去执行SQL。但是这种方法存在一些问题,对于LONG RAW、BLOB等大
字段不知道如何使用SQL语句提交,如果那位有方法,那就可以解决了。
 
[:)][?]
重新声明:
经过我今天的测试发现,不管如何提交仍存在
"Record not found or changed by another user"的问题。
测试方法还是上面提过的。
所以请各位多提些建议。
我现在用的也是 Midas.dll 7.0,问题并没有解决。[:(][:(!]
 
我找到一个解决方法,原因就是varchar2类型的数据当为''(空)时,当提交到应用服务器
上的时候,应用服务器去回记录的时候变成Null,所造成的。
解决方法:
修改VCL中的DBCtrls.pas单元中的TDBEdit,TDBMomo等可以输入空字符数据的类,在它的
UpdateData方法修改如下:
procedure TDBEdit.UpdateData(Sender: TObject);
begin
ValidateEdit;
if Trim(Text) = '' then
FDataLink.Field.AsVariant := Null
else
FDataLink.Field.Text := Text;
end;

procedure TDBMemo.UpdateData(Sender: TObject);
begin
if Trim(Text) = '' then
FDataLink.Field.AsVariant := Null
else
FDataLink.Field.AsString := Text;
end;
 
顶部