Lazarus SQLQuery - problem z automatycznym close

0

Witam, W Lazarusie przy zapytaniach mam problem z automatycznym Close komponentu SQLQuery.
Kod wygląda następująco:

 SQLQueryFunkcje.SQL.Clear;
   SQLQueryFunkcje.SQL.Add('select A.nr_wz,B.data_wystawienia from sprzedaz_dane A left outer join wz_dane B on(A.id_dane_wz=B.id) where A.nr_wz is not null and A.nr_fv is null and A.anulowano is null');
   SQLQueryFunkcje.Open;
   while not SQLQueryFunkcje.Eof do
   begin
    DecodeDateFully(SQLQueryFunkcje.FieldByName('data_wystawienia').AsDateTime,R,M,D,DT);
    if M<Mnow then
    begin
     if Length(MsgAlarm1)=0 then
     begin
      MsgAlarm1:=' ! Z poprzeniego miesiąca niezafakturowano Wz: '+SQLQueryFunkcje.FieldByName('nr_wz').AsString;
     end else
     begin
      MsgAlarm1:=MsgAlarm1+', '+SQLQueryFunkcje.FieldByName('nr_wz').AsString;
     end;
    end;
    SQLQueryFunkcje.Next;
   end;
   if Length(MsgAlarm1)>0 then
   begin
    Priorytet:=2;
    MsgAlarm1:=MsgAlarm1+'. Należy zmienieć datę systemową i zafakturować !'
   end;
  
  if Length(MsgInfo1)>0 then
  begin
  
<u> //SQLQueryFunkcje.Close; ---- JEŻELI TU JEST CLOSE PROBLEM ZNIKA</u>

   DecodeDateFully(DataDzis,R,M,D,DT);
   SQLQueryFunkcje.SQL.Clear;
   SQLQueryFunkcje.SQL.Add('select count(nr_sprzedazy) ilosc from sprzedaz_dane where nr_wz is not null and nr_fv is null and anulowano is null');
   SQLQueryFunkcje.Open;
  
   if SQLQueryFunkcje.FieldByName('ilosc').AsInteger=0 then //jezeli wszystko zafakturowane - czyszczenie tresci komunikatu MsgInfo1 - utworzonego domyslnie .
    MsgInfo1:='';
   
  end;                              

Jeżeli nie zamknę SQLQueryFunkcje ręcznie pojawia się błąd po uruchomieniu procedury: SQLQueryFunkcje : Field not found : "ilosc".
Pod Delphi ten kod działa poprawnie.

2

Poprawnie jest świadomie zamykać Query po zakończonych operacjach.

2

Ja zawsze piszę tak:

with DataModule.Query, SQL do
  begin
    Close;
    Clear;
    Add('SELECT.....');
    Open;
  end;
3
amprogramming napisał(a):

Witam, W Lazarusie przy zapytaniach mam problem z automatycznym Close komponentu SQLQuery.

/ciach/
Ale gdzie tam masz automatyczne zamykanie, bo nie wiem o co chodzi?

Jeżeli nie zamknę SQLQueryFunkcje ręcznie pojawia się błąd po uruchomieniu procedury: SQLQueryFunkcje : Field not found : "ilosc".
Pod Delphi ten kod działa poprawnie.

I prawidłowo; ponieważ jeśli próbujesz zrobić Open na otwartym Query (czyli spełnia warunekQuery.Active = True) to prawdopodobnie... nic się nie wydarzy.
Nie mam źródeł FPC, więc nie sprawdzę ale w Delphi metoda open jest zaimplementowana tak:

procedure TDataSet.Open;
begin
  Active := True;
end;

A więc widać, że ustawiany jest atrybut Active; zatem musimy zobaczyć jak wygląda setter dla Active, a on wygląda (co do zasady) tak:

procedure TDataSet.SetActive(Value: Boolean);
begin
    if Active <> Value then
    begin
        // otwieraj DataSeta...
    end;
end;

A więc skoro masz aktywny DataSet i robisz mu ponowne Open, to nic się nie dzieje.

Masz błąd o braku odnalezienia pola Ilosc, ponieważ w pierwszym zapytaniu nie istnieje to pole.
Wyobraź sobie, że w obu zapytaniach będzie pole o tej samej nazwie.
Wtedy nawet mógłbyś nie zauważyć błędu, ale raczej na pewno nie dostałbyś tej wartości, której oczekujesz.

1
wloochacz napisał(a):

Nie mam źródeł FPC, więc nie sprawdzę ale w Delphi metoda open jest zaimplementowana tak:

[…]

Tak samo jest jak w Delphi. Natomiast setter tej właściwości wygląda tak (po sformatowaniu…):

procedure TDataSet.SetActive(AValue: Boolean);
begin
  if AValue and (FState = dsInactive) then
  begin
    if csLoading in ComponentState then
    begin
      FOpenAfterRead := True;
      Exit;
    end
    else
    begin
      DoBeforeOpen();
      FEnableControlsEvent := deLayoutChange;
      FInternalCalcFields := False;
      try
        FDefaultFields := FieldCount = 0;
        OpenCursor(False);
      finally
        if FState <> dsOpening then
          OpenCursorComplete();
      end;
    end;
    FModified:=False;
  end
  else
    if not AValue and (FState <> dsinactive) then
    begin
      DoBeforeClose();
      SetState(dsInactive);
      CloseCursor();
      DoAfterClose();
      FModified := False;
    end
end;

Open wywołany drugi raz nie robi absolutnie nic – dlatego Close jest konieczny.

1 użytkowników online, w tym zalogowanych: 0, gości: 1