关于clientdataSet的locate无法正确定位的问题?(100分)

  • 主题发起人 主题发起人 yh
  • 开始时间 开始时间
Y

yh

Unregistered / Unconfirmed
GUEST, unregistred user!
我作了这样的一个应用:
连接下列VCL:clientdataset-privder-query,
其中:query.requestlive:=true.
Query.SQL.Text:='select * from mytable where qj=:qj
当clientdateset打开时,我取得了正确的结果,对其进行计算的过程中
我对clientDataSEt发出了locate
if clientdataSEt.locate('qj,bm,i0,i1,i2,i3,i4...i9',
vararrayof([tpp1.FieldbyName('qj').AsString;
tpp1.FieldByName('bm').AsString;
tpp1.FieldByName('i0').AsString;
...
tpp1.FieldByName('i9').AsString
]),[])
假设clientDataSet表中存在这样的值:
qj='1999-01'
bm='11110001'
i0=''
i1=''
...
i9=''
则当tpp1当前行的值为上面值也查不到。
 
字段名用";"分隔, 不是","
 
将 ';'和','用反了,

if clientdataSEt.locate('qj;bm;i0;i1;i2;i3;i4...i9', ";"
vararrayof([tpp1.FieldbyName('qj').AsString,
tpp1.FieldByName('bm').AsString,
tpp1.FieldByName('i0').AsString, //用","
...
tpp1.FieldByName('i9').AsString
]),[])
 
是用;分隔,但问题依旧。
怀疑是delphi clientDataSet的bug!
 
只用一个字段, 能成功吗?
 
To SeaSky ,关于我的问题,只用一个字段是什么意思,不明白?
 
是这么回事,我也碰到过,没解决.
只好绕弯子,建立索引,用FindKey定位纪录,建个索引很方便的,就这么办吧.
 
to wgzhang
索引也建了,还是不行这是我的测试代码:
cdsFxye.AddIndex('mykey', 'qj;bm;i0;i1;i2;i3;i4;i5;i6;i7;i8;i9',
[ixPrimary,ixUnique], '', '', 0);
cdsFxye.IndexName:='mykey';//定义索引

if not cdsFxye.Locate('qj;bm;i0;i1;i2;i3;i4;i5;i6;i7;i8;i9',
VarArrayof([
qPz2.FieldByName('qj').AsString,
qPz2.FieldByName('km').AsString,
qPz2.FieldByName('i0').AsString,
qPz2.FieldByName('i1').AsString,
qPz2.FieldByName('i2').AsString,
qPz2.FieldByName('i3').AsString,
qPz2.FieldByName('i4').AsString,
qPz2.FieldByName('i5').AsString,
qPz2.FieldByName('i6').AsString,
qPz2.FieldByName('i7').AsString,
qPz2.FieldByName('i8').AsString,
qPz2.FieldByName('i9').AsString
]),
[loPartialKey]) then
{ if not cdsFxye.FindKey([
qPz2.FieldByName('qj').AsString,
qPz2.FieldByName('km').AsString,
qPz2.FieldByName('i0').AsString,
qPz2.FieldByName('i1').AsString,
qPz2.FieldByName('i2').AsString,
qPz2.FieldByName('i3').AsString,
qPz2.FieldByName('i4').AsString,
qPz2.FieldByName('i5').AsString,
qPz2.FieldByName('i6').AsString,
qPz2.FieldByName('i7').AsString,
qPz2.FieldByName('i8').AsString,
qPz2.FieldByName('i9').AsString
]) then}
begin
cdsFxye.AppendRecord([
qPz2.FieldByname('qj').AsString,
qPz2.FieldByname('km').AsString,
qPz2.FieldByname('i0').AsString,
qPz2.FieldByname('i1').AsString,
qPz2.FieldByname('i2').AsString,
qPz2.FieldByname('i3').AsString,
qPz2.FieldByname('i4').AsString,
qPz2.FieldByname('i5').AsString,
qPz2.FieldByname('i6').AsString,
qPz2.FieldByname('i7').AsString,
qPz2.FieldByname('i8').AsString,
qPz2.FieldByname('i9').AsString
]);
end;
cdsFxye.Edit;
另:关于这一问题在inprise delphi forum上也问了,没结果.下面是问题的说法
大家再看看,表达的是否清楚.

我已经试了locate与findkey两种方法。
思路是这样的:
根据当前qPz2的记录值查找cdsFXYE.找不到则为cdsFXYE增加一条记录.
假若qPz2的值为:
qj='1999-01'
km='11010001'
其他值字段为'';
明明在fxye中存在这样的记录,则第一次无法查到,于是代码执行AppendRecord,
写到这,已经知道在cdsFXYE中已经存在这样的两条记录,第一条是从Query中得到,
后一条是新增的,
奇怪的是,当qPz2再遇见这样的记录时,则能够定位于这条后增加的记录上。

不知所以然,试着看了一下DBclient.pas,即clientDataSet的源码,但水
平有限,只是看到clientDataSet.Locate调用了clientDataSet.LocateRecord,
便看不明白了。
 
我的意思是 先试着使用
if not cdsFxye.Locate('qj',
VarArrayof([
qPz2.FieldByName('qj').AsString]),[]) then
查找第一个字段匹配的值, 如果能找到, 再添一个字段, 如此这般,
看看是哪个字段上出问题了.

 
今天特意试了一下,发现可以,DBDEMOS
Query1与你设置的一样,select * from customer where country='US'

ClientDataset1.Locate('CustNo;Country',vararrayof([StrtoInt(edit1.Text),'US']),[]);
大概是安装了5.37和Update2,3的原因吧.
看看你的版本.

 
to seaSky:
放一个字段好用,没发现问题。

同样的语句,换成Query解决,怀疑是clientDataSet的bug.
 
你逐渐加数量呀. 两个字段的结果怎么样, 三个呢? 会不会对数量有限制?
 
to SeaSky:

不会对数量有限制,从dbclient.pas源码中能看出来。
问题很可能是因为字段值为''造成的。

我的版本是5.108,加了patch3.版本应没问题。
再看看我第二次的详细说明,注意这么一句:
假若qPz2的值为:qj='1999-01'km='11010001',其他值字段为'';

问题就出在其他字段为''的情况,如果其他字段都有值,不为'',可以正常执行。
 
Hehe , 早说呀, 你的其他字段的值是不是Null值呀 , Null值的字段有如下特性:

field.asstring=''
field.value= null

记住 Null <> ''

所以你的程序应该这样写:
if not cdsFxye.Locate('qj;bm;i0;i1;i2;i3;i4;i5;i6;i7;i8;i9',
VarArrayof([
qPz2.FieldByName('qj').AsString,
qPz2.FieldByName('km').AsString,
qPz2.FieldByName('i0').AsString,
qPz2.FieldByName('i1').AsString,
qPz2.FieldByName('i2').AsString,
qPz2.FieldByName('i3').AsString,
qPz2.FieldByName('i4').AsString,
qPz2.FieldByName('i5').AsString,
qPz2.FieldByName('i6').AsString,
qPz2.FieldByName('i7').AsString,
qPz2.FieldByName('i8').AsString,
qPz2.FieldByName('i9').AsString
]),
[loPartialKey]) then
{ if not cdsFxye.FindKey([
qPz2.FieldByName('qj').value,
qPz2.FieldByName('km').value,
qPz2.FieldByName('i0').value,
qPz2.FieldByName('i1').value,
qPz2.FieldByName('i2').value,
qPz2.FieldByName('i3').value,
.......
])

 
aiyaya ,
突然发现贴错了. 重新改过
if not cdsFxye.Locate('qj;bm;i0;i1;i2;i3;i4;i5;i6;i7;i8;i9',
VarArrayof([
qPz2.FieldByName('qj').Value,
qPz2.FieldByName('km').value,
qPz2.FieldByName('i0').value,
qPz2.FieldByName('i1').value,
qPz2.FieldByName('i2').value,
qPz2.FieldByName('i3').value,
qPz2.FieldByName('i4').value,
qPz2.FieldByName('i5').value,
qPz2.FieldByName('i6').value,
qPz2.FieldByName('i7').value,
qPz2.FieldByName('i8').value,
qPz2.FieldByName('i9').value,
]),
[loPartialKey]) then

需要注意的是 . asstring的方式得到的并不是真实的值 , 只有Value属性
才反映字段的真值. 同样日期和数值字段一样有asstring属性, 但只代表转
化为字符串的属性.
 
还是放弃Locate吧,因为Borland也承认Locate有bug
简单一点,使用Query,写一段SQL。大不了,多写几个Where

 
SeaSky完全正确,是asString与Value的引用的区别,即是
null与''的区别。
多谢大家的帮助,还是分一点积分给大家,SeaSky不要生气:)
 
后退
顶部