问题描述
我有一个 master 和一个 detail TAdoQuery
,分别称为 FMaster
和 FDetail
。它们通过数据源 FMasterSource
连接。详细查询有一个参数,它会根据主查询自动填充和更新。
现在的问题是:在执行 FDetail.Locate
(或实际上是 FDetail.Recordset.Clone
)后,FMaster.Next
在尝试使用新参数重新查询 FDetail
时抛出异常:
try
FMaster.Open;
FDetail.Open;
FDetail.Locate('Id',2,[]);
FMaster.Next; {<== throws Exception with ADO Errorcode 0x80040e05}
finally
FDetail.Close;
FMaster.Close;
end;
根据this List,错误代码0x80040e05
表示“对象已经打开”。
- 问题似乎是,
FDetail.Locate
创建了底层 Ado 记录集的克隆以供以后使用,并保存它。因此,我们可以将 Locate 替换为recordsetClone := FDetail.Recordset.Clone(adLockReadOnly);
(其中uses Winapi.ADOInt
)并得到相同的错误。 - 在
FMaster.Next
中,在设置 MasterId 的新参数后尝试重新查询FDetail
会引发异常。这发生在TCustomADODataSet.RefreshParams
。 - 当您断开 Detail 与 Master 的连接时,一切正常。手动设置
FDetail
的参数效果很好。
我错过了什么? 这是 VCL 中的错误吗? 还是又一个奇怪的 ADO 错误?
源代码
我使用的是 Oracle 11g XE 和 Delphi 10.4 Sydney。
Oracle 表:
drop table Detail;
drop table Master;
create table Master (
Id NUMBER(2) not null,constraint MasterPK primary key (Id)
);
create table Detail (
Id NUMBER(2) not null,MasterId NUMBER(2),constraint DetailPK primary key (Id),constraint DetailFK foreign key (MasterId) references Master(Id)
);
insert into Master values (1);
insert into Master values (2);
insert into Detail values (1,1);
insert into Detail values (2,1);
insert into Detail values (3,2);
德尔福代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
//Initializing...
FConnection.Provider := 'OraOLEDB.Oracle.1';
FConnection.ConnectionString := 'Provider=OraOLEDB.Oracle.1;Password=xxxx;Persist Security Info=True;User ID=TEST;Data Source=XE';
FConnection.LoginPrompt := False;
FConnection.KeepConnection := False;
FMaster.Connection := FConnection;
FMaster.SQL.Text := 'select Id from Master';
FMaster.CursorLocation := clUseServer;
FMaster.CursorType := ctStatic;
FMasterSource.DataSet := FMaster;
FDetail.Connection := FConnection;
FDetail.DataSource := FMasterSource;
FDetail.SQL.Add('select Id,MasterId from Detail where MasterId = :Id');
FDetail.Parameters[0].DataType := ftInteger;
FDetail.CursorLocation := clUseServer;
//Do stuff
try
FMaster.Open;
FDetail.Open;
//FDetail.Locate('Id',[]);
recordsetClone := FDetail.Recordset.Clone(adLockReadOnly);
FMaster.Next; {<== throws Exception with ADO Errorcode 0x80040e05}
finally
FDetail.Close;
FMaster.Close;
end;
end;
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)