三层下EDIT,POST的问题。感觉真让我迷惑呀?!(200分)

W

wumeng

Unregistered / Unconfirmed
GUEST, unregistred user!
我用的是Win2k,d5,TSocketConnection,SQL2K。三层下EDIT,POST的问题。
我先找到DBNavigate连接的TClientDataSet,然后用它的EDIT,POST。
如果我只修改几个字段(1,2,3,4个字段都试过),修改时,只要不包括
主键,它总是修改DBGRID中的第一条,而不是当前记录。但如果你修改的字段
包含主键,修改的结果一正确。下面是我的代码。
procedure TfrmMatAdd.dbnMasterBeforeAction(Sender: TObject;
Button: TNavigateBtn);
var
cdsDelete: TClientDataSet;
begin
inherited;
if Button<>nbDelete then
Exit;
cdsDelete:= TClientDataSet(TDBNavigator(Sender).DataSource.DataSet);
cdsDelete.Edit;
cdsDelete.FieldByName('status').Value:='D';
cdsDelete.Post;
abort;
end;
 
我想你可以检查两个地方看看:
1、看看服务器的更新模式设置(即PROVIDER的UPDATEMODE);
2、检查一下客户端CLIENTDATASET的DELTA内容;
同时,你也可以使用SQL SERVER的事件查看器来监视应用程序发给数据库的SQL语句情况。
 
同意楼上!
 
怎么检查客户端CLIENTDATASET的DELTA内容???请详细说明。
》》你也可以使用SQL SERVER的事件查看器来监视应用程序发给数据库的SQL语句情况。
这个我试了一下,也没试出来怎么用。
 
1、检查CLIENTDATASET的DELTA内容的方法可以:再新建一个CLIENTDATASET,然后将要监视的
CLIENTDATASET的DELTA内容赋给刚才新建的DATA即可。如果不懂原理,可参看李维三层结构之系统篇的内容;
2、事件见识器你设定好过滤的条件就能看见了。
 
>>可以使用SQL SERVER的事件查看器来监视应用程序发给数据库的SQL语句情况。
我观察的结果是这样的:
UPDATE "qxerp".."TbnInstMatAdditions" SET "matAddNo"=@P1,"status"=@P2
WHERE "matAddNo"=@P3 AND "status"=@P4
它根本没带参数的数值,不知道是不是我的 事件查看器 的设置不对。。。
李维三层结构ADO这本书中的例子,它观察的结果是这样的:
sp_executesql N'UPDATE "pubs".."ADOTestDatas" SET "Name"=@P1 WHERE
"ID"=@P2 AND "Name"=@P3', N'@P1 varchar(9),@P2 varchar(10),@P3
varchar(10)', 'Gordon Li', 'V855544347', 'cxiianffdn'
也就是说,他能看到参数的数值。
 
你的服务器端的updatemode是whereall吗?
 
>>你的服务器端的updatemode是whereall吗?
不是,我用的是upWhereChanged.
 
那就改成whereall吧,应该可以解决问题了.
 
>>那就改成whereall吧,应该可以解决问题了.
改成这样的话就会出这样的错误:record Changed by another user.
其实,服务器端的updatemode的默认值就是whereall。我是因为以上的错误才改成
upWhereChanged的。这几个值我都试过了。用upWhereKeyOnly的话,会报告找不到
关键字的错误。。。
 
你的resolvedodataset是设置为false吗?要设置为false的.
 
>>你的resolvedodataset是设置为false吗?
false和True我都试过了,这个属性的意思是你要怎么样更新数据。下面是帮助中说的。
这个属性一般来说要设置成TRUE,因为只有这样用户才能看到数据确实被改变了,
程序就不用再查询一次了,减少了网络的流量。
另外,我设置它为TRUE时,它在程序界面上修改的也确实是我定位的那条记录,只是
再次查询时才发现它改变的是第一条记录。。。
Set ResolveToDataSet to specify how updates are applied.
When ResolveToDataSet is True, the Resolver property is set to
a TDataSetResolver component, which applies updates directly to
the dataset specified by the DataSet property. This can be useful
if the application uses the events on the dataset component or if
the datasetdo
es not represent the data from a database server
(for example, a client dataset).
When ResolveToDataSet is False, the Resolver property is set to
a TSQLResolver component, which applies updates directly to the
database server associated with DataSet. This can be more efficient,
because it skips the intermediate step of using the dataset.
 
老兄,难道上面的帮助你没看明白吗?难道李维的宝书你没看吗?设置为False的意思是由
Provider自己更新数据,一方面更有效率,二方面也不会出现你所说的错误.也就是说
要设置为:
resolvetodataset := false;
updatamode := upwhereall;
 
to michael.fly:
所有的这几种组合我都试过了。只要是你改变的不是关键字,但你的前面的记录又和你现在
要改变的记录有相同的值,它改变的就是前面的记录。。。即使你改变的不只是一个栏位。
 
我在客户端用DBEDIT连接所有的字段,然后我查询出来几条记录(它们除关键字不同外,
其它字段几乎都相同,这主要是要测试我上面说的)。修改其中的一条(这条不是第一
条),保存。这时,你在程序界面上看,你修改的就是你想改的这条。
但你刷新一下(或到数据库中查看)。你实际改变的是第一条记录。。。
我真有点绝望了,难道这就是BORLAND 功能强大的产品???
 
这怎么可能呢?我有一次也是碰到与你类似的问题,后来我通过SQL SERVER的事件监视器
进行查找,然后采用上述的方法,最后解决了问题.
如不介意的话,把你的程序的片断(出错部分)发过来如何?
或者建议你建立一个原型系统,就针对这个问题,进行一下测试.
另外,不要对BORLAND失望,绝对是我们的问题.
 
to michael.fly:
所有的这几种组合我都试过了。现在发现,只有两种情况能用,就是:
resolvetodataset := false;
updatamode := upwhereall;
resolvetodataset := True;
updatamode := upWhereChanged;
下面是我测试的结果。
False
1.upWhereAll: 单用户时正确!!!如果多用户多个中间层时有问题。
2.upWhereKeyOnly :找不到主关键字!!!Unable to find record. No key specified
3.upWhereChanged:结果不对,会更新所有相同的记录!!!
True
1.upWhereAll: Record changed by another user.
2.upWhereKeyOnly :找不到主关键字!!!Unable to find record. No key specified
3.upWhereChanged:结果不对,会更新相同记录的第一条!!!
老板为了避免多用户时出现问题,让我们用resolvetodataset := True;但测试下来,
只有 updatamode := upWhereChanged;时程序才勉强运行,但更新时还发生
“结果不对,会更新相同记录的第一条!!!” 的错误。
回过头一说,既然其他的组合不能用BORLAND为什么还给其他的组合呢???
这至少也要说是它的错误吧?!(我指的是6种组合只有1种可用)
 
你用的是ADO吗?
 
>>你用的是ADO吗?
是的,当我用 resolvetodataset := True;(updatamode := upWhereChanged;只有这个
才能用。。。)时,我按书上说,取得ADO的动态属性。也就是相当于updatamode
这个属性,但我发现它没有起作用。。。
procedure TrdmPcAppSvr.setAdoWhereKeyOnly(ADODataSet:TADODataSet);
var
rs_ : _RecordSet;
pty : Property_;
pties : Properties;
begin
rs_ := ADODataSet.Recordset;
pties := rs_.Properties;
pty := pties. Get_Item('Update Criteria');
pty.Value:=1;// 0~3
frmPcSvr.Caption:=inttostr(pty.Value);
end;

我还测试到当我取得下面的数据时,它还是正确的。
procedure TrdmPcAppSvr.dspInOutPutUpdateData(Sender: TObject;
DataSet: TClientDataSet);
begin
frmPcSvr.ClientDataSet1.data:=DataSet.data;
end;
但它更新的结果却不正确。它更新的是第一笔。。。
 
我又作了一个两层次的程序专门测试这个问题,发现它改变的是正确的。
还有,我也作了一个两层次的主细档的程序,当主档选择出来只有一条记录时,
细档的结果也是正确的,看来这就是BORLAND三层次的BUG了!!!
 
顶部