У меня есть MasterQry и SlaveQry на форме.MasterQry выглядит примерно так:
select * from Header where Active = 1
.
В этом событии AfterScroll у меня есть следующее:
select * from Slave where HeadID=:Header.ID
Теперь, если я сделаю:
if MasterQry.Active then MasterQry.Close;
MasterQry.Open;
, это работает безупречно, если у меня есть большезатем одна запись, но она не работает, если у меня есть только одна.
Даже если я делаю MasterQry.First;
, ничего не происходит.
Если я пытаюсь MasterQry.AfterScroll(MasterQry)
, я получаю нарушение прав доступа.
Я выполнял рефакторинг своего кода и пытался сделать его более компактным, потому что я использовал много Open Open Locate 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;
ОБРАТИТЕ ВНИМАНИЕ, этот код не универсален, но идеально подходит для моих нужд.Я заметил, что событие AfterScroll здесь запускается, даже если у меня есть только одна запись в MasterQry, или даже если у меня вообще нет записи.Я был действительно счастлив, я тестировал его несколько раз, и он дал правильные результаты.
Я проверил процедуры TADOQuery.First и TADOQuery.Locate, и у них был DoAfterScroll, но он не был запущен с одной записью или без записи.(SlaveQry был оставлен открытым в нежелательном состоянии)
Я много гуглил по этому поводу, но не смог найти причину.
Мой вопрос : почему это работает?почему AfterScroll срабатывает с одной или без записи.
Спасибо.
ОБНОВЛЕНИЕ
Я могу воспроизвести это только с помощью Microsoft SQL.Таким образом, чтобы проверить это, вам нужно.Две таблицы.
В MasterTable добавить две записи (ID, текст, активный)
1 Первая 1
2 Вторая 1
в SlaveTable добавить две или более записи (ID, HeadID, текст)
1,1, First-1
2,1, First-2
3,2, Second-1
4,2, Second-2
Теперь добавьте в форму один ADOConnection two ADOQueries .
в MainQuery у вас есть следующий текст
Select * from MasterTable where Active=1
в SlaveQuery у вас есть следующий текст
select * from SlaveTable where HeadID=:HeadID
на MainQuery.BeforeOpen у вас есть это:
MainQuery.AfterScroll:=nil;
на MainQuery.AfterScroll у вас есть это:
if SlaveQuery.Active then SlaveQuery.Close;
SlaveQuery.Parameters.ParamByName('HeadID').Value:=MainQueryID.Value;
SlaveQuery.Open;
в MainQuery.AfterOpen у вас есть это:
MainQuery.AfterScroll:=MainQueryAfterScroll;
Добавьте Button в эту форму:
Button1Click Событие содержит следующее:
if MasterQuery.Active then MasterQuery.Close;
MasterQuery.Open;
Таким образом, если вы теперь присоединяете сетку к обоим запросам, вы можете видеть, что она отлично работает.
Не закрывая программу, зайдите в диспетчер SQL Server и выполните следующую инструкцию обновления:
update MasterTable set Active=0
Нажмите кнопку Button1 в форме еще раз:
MasterQuery isEmtpy, SlaveQuery остался в последнем открытом состоянии.
Чтобы исправить это, вам нужно изменить Button1Click следующим образом:
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 на ноль, а затем обратно снова как-то запускает AfterScroll, даже если он имеет 1 запись или пуст.