Delphi ADOQuery余色未触发,只有一条记录/没有记录
我在表格上有一个主从。 大师是这样的:Delphi ADOQuery余色未触发,只有一条记录/没有记录,delphi,tadoquery,Delphi,Tadoquery,我在表格上有一个主从。 大师是这样的: 从活动=1的标题中选择* 在余震事件中,我有以下几点: 从HeadID=:Header.ID的从属位置选择* 现在如果我这样做: if MasterQry.Active then MasterQry.Close; MasterQry.Open; 如果我有一张以上的唱片,这项功能就完美无瑕,但如果我只有一张唱片,它就不起作用 即使我先掌握了MasterQry什么也没发生 如果我尝试MasterQry.aftercroll(MasterQry)我会遇到访问冲
从活动=1的标题中选择*
在余震事件中,我有以下几点:
从HeadID=:Header.ID的从属位置选择*
现在如果我这样做:
if MasterQry.Active then MasterQry.Close;
MasterQry.Open;
如果我有一张以上的唱片,这项功能就完美无瑕,但如果我只有一张唱片,它就不起作用
即使我先掌握了MasterQry代码>什么也没发生
如果我尝试MasterQry.aftercroll(MasterQry)
我会遇到访问冲突
我正在重构我的代码,并试图使其更加紧凑,因为我做了大量的打开-关闭定位ID(需要刷新数据以获得实际状态,是否锁定等),我做到了这一点:
function RefreshQuery(AQuery : TADOQuery; ID : integer) : boolean ; overload;
var AfterOpen,AfterScroll : TDataSetNotifyEvent;
begin
result:=false;
AfterOpen := AQuery.AfterOpen;
AfterScroll := AQuery.AfterScroll;
AQuery.AfterOpen:=nil;
AQuery.AfterScroll:=nil;
if AQuery.Active then AQuery.Close;
AQuery.Open;
if not AQuery.Locate('id', ID, []) then
result:=false
else
result:=true;
AQuery.AfterOpen:=AfterOpen;
AQuery.AfterScroll:=AfterScroll;
if Assigned(AQuery.AfterScroll) then
AQuery.AfterScroll(AQuery);
end;
请注意,此代码不是通用的,但完全适合我的需要。我注意到这里的余弦事件正在被触发,即使我在MasterQry中只有一张记录,或者即使我根本没有。我真的很高兴,我测试了很多次,结果都是正确的
我检查了TADOQuery.First和TADOQuery.Locate过程,两个过程都有DoAfterScroll,但它不是在一条记录或没有记录的情况下触发的。(从属开关在非期望状态下保持打开状态)
为此我在谷歌上搜索了很多,但找不到原因
我的问题是:为什么这样做?为什么余弦发射时只有一个或没有记录
多谢各位
更新
我只能用Microsoft SQL重现这一点。所以为了测试这个,你需要。两张桌子
在主表中添加两条记录(ID、文本、活动)
1前1
2秒1
在slaveable中添加两条或多条记录(ID、HeadID、Text)
1,1,第一-1
二、一、二
3,2,秒-1
4,2,2秒
现在进入表单1ADOConnectiontwoadoconquerys
在main查询中有以下文本
Select * from MasterTable where Active=1
在SlaveQuery中有以下文本
select * from SlaveTable where HeadID=:HeadID
在MainQuery.BeforeOpen上,您有:
MainQuery.AfterScroll:=nil;
if SlaveQuery.Active then SlaveQuery.Close;
SlaveQuery.Parameters.ParamByName('HeadID').Value:=MainQueryID.Value;
SlaveQuery.Open;
MainQuery.AfterScroll:=MainQueryAfterScroll;
在MainQuery.AfterScroll上,您有以下内容:
MainQuery.AfterScroll:=nil;
if SlaveQuery.Active then SlaveQuery.Close;
SlaveQuery.Parameters.ParamByName('HeadID').Value:=MainQueryID.Value;
SlaveQuery.Open;
MainQuery.AfterScroll:=MainQueryAfterScroll;
在MainQuery.AfterOpen上,您有:
MainQuery.AfterScroll:=nil;
if SlaveQuery.Active then SlaveQuery.Close;
SlaveQuery.Parameters.ParamByName('HeadID').Value:=MainQueryID.Value;
SlaveQuery.Open;
MainQuery.AfterScroll:=MainQueryAfterScroll;
将按钮添加到此表单中:
Button1Click事件包含以下内容:
if MasterQuery.Active then MasterQuery.Close;
MasterQuery.Open;
因此,如果您现在将网格附加到两个查询中,您可以看到它完全符合要求
在不关闭程序的情况下,进入SQL Server管理器并运行以下update语句:
update MasterTable set Active=0
再次按下窗体上的按钮1:
主查询是Emtpy,而SlaveQuery处于上次打开状态
要解决此问题,您需要更改按钮1,单击如下所示:
var AfterOpen,AfterScroll : TDataSetNotifyEvent;
begin
AfterOpen := AQuery.AfterOpen;
AfterScroll := AQuery.AfterScroll;
AQuery.AfterOpen:=nil;
AQuery.AfterScroll:=nil;
if AQuery.Active then AQuery.Close;
AQuery.Open;
AQuery.AfterOpen:=AfterOpen;
AQuery.AfterScroll:=AfterScroll;
if Assigned(AQuery.AfterScroll) then
AQuery.AfterScroll(AQuery);
end;
现在它开始工作了。我不知道为什么,因为MasterQuery.First应该触发DoAfterScroll,但什么也没发生。
似乎是将AfterScroll设置为nil,然后再返回,即使它有1条记录或为空,也会以某种方式触发AfterScroll。正如我在评论中所说的,刷新查询中的大部分代码都不需要,
链接主->详细数据集时,应“正常工作”。事实上,您的RefreshQuery
应该根本不需要
我仅通过删除组件就基于主表和从表创建了一个最小的项目
从托盘中,将它们连接起来,只添加下面Form1.FormCreate中的代码。这个
从网格的内容正确地跟踪主网格,包括以下情况:
没有匹配的从属记录,即从属网格显示为空。请注意,不存在任何需要的数据事件,即无aftercroll
和无Locate
等调用
type
TForm1 = class(TForm)
dsMaster: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
DBGrid2: TDBGrid;
DataSource2: TDataSource;
DBNavigator2: TDBNavigator;
ADOConnection1: TADOConnection;
qMaster: TADOQuery;
qSlave: TADOQuery;
qSlaveID: TIntegerField;
qSlaveHeaderID: TIntegerField;
qSlaveAText: TWideStringField;
procedure FormCreate(Sender: TObject);
public
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
qMaster.SQL.Text := 'select * from mastertable';
qSlave.DataSource := dsMaster;
qSlave.SQL.Text := 'select * from slavetable where headerid = :id';
// NOTE: because the DataSource property of qSlave is set to dsMaster,
// the ` = :id` tells the Ado run-time code to get the value of the
// ID field in the qMaster table.
qMaster.Open;
qSlave.Open;
end;
如果您希望在其他用户更改主表或从表中的记录时刷新主表或从表,可以这样做:
procedure TForm1.Button1Click(Sender: TObject);
begin
qMaster.Refresh;
end;
但是请注意,需要在Sql Server上正确设置该表。只要将ID字段设置为主键,并且/或者在服务器上设置了唯一的索引,调用Refresh
应该可以正常工作,但是如果不这样做,您将收到一条错误消息,大意是“没有足够的键信息用于更新或刷新”。当然,您可以在计时器上进行刷新(但不要太频繁地调用它,即每几秒钟调用一次以上)。正如我在评论中所说的,您的刷新查询中的大部分代码应该是不必要的,
链接主数据集->详细数据集应该“正常工作”。事实上,RefreshQuery
应该根本不需要
我仅通过删除组件就基于主表和从表创建了一个最小的项目
从pallete,将它们连接起来,只添加下面Form1.FormCreate中的代码
从网格的内容正确地跟踪主网格,包括以下情况:
没有匹配的从属记录,即从属网格显示为空。请注意,没有任何需要的数据事件,即没有aftercroll
和Locate
等调用
type
TForm1 = class(TForm)
dsMaster: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
DBGrid2: TDBGrid;
DataSource2: TDataSource;
DBNavigator2: TDBNavigator;
ADOConnection1: TADOConnection;
qMaster: TADOQuery;
qSlave: TADOQuery;
qSlaveID: TIntegerField;
qSlaveHeaderID: TIntegerField;
qSlaveAText: TWideStringField;
procedure FormCreate(Sender: TObject);
public
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
qMaster.SQL.Text := 'select * from mastertable';
qSlave.DataSource := dsMaster;
qSlave.SQL.Text := 'select * from slavetable where headerid = :id';
// NOTE: because the DataSource property of qSlave is set to dsMaster,
// the ` = :id` tells the Ado run-time code to get the value of the
// ID field in the qMaster table.
qMaster.Open;
qSlave.Open;
end;
如果您希望在其他用户更改主表或从表中的记录时刷新主表或从表,可以这样做:
procedure TForm1.Button1Click(Sender: TObject);
begin
qMaster.Refresh;
end;
但是请注意,需要在Sql Server上正确设置该表。只要将ID字段设置为主键,并且/或者在服务器上设置了唯一的索引,则调用Refresh
应该可以正常工作,但如果不这样做,您将收到一条错误消息,其大意是“没有足够的关键信息用于更新或刷新。”您当然可以在计时器上进行刷新(但不要太频繁,即每几秒钟调用一次以上)。您的问题似乎自相矛盾:您说“如果我有多条记录,这项功能将完美无瑕,但如果我只有一条记录,则无法正常工作”但是为什么余弦发射时只有一次或没有记录