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
应该可以正常工作,但如果不这样做,您将收到一条错误消息,其大意是“没有足够的关键信息用于更新或刷新。”您当然可以在计时器上进行刷新(但不要太频繁,即每几秒钟调用一次以上)。

您的问题似乎自相矛盾:您说“如果我有多条记录,这项功能将完美无瑕,但如果我只有一条记录,则无法正常工作”但是为什么余弦发射时只有一次或没有记录