Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Operation bei geschlossener Datenmenge nicht ausführbar (https://www.delphipraxis.net/107946-operation-bei-geschlossener-datenmenge-nicht-ausfuehrbar.html)

Nuclear-Ping 5. Feb 2008 06:32

Datenbank: Advantage Local Server • Version: 7 • Zugriff über: TQuery

Operation bei geschlossener Datenmenge nicht ausführbar
 
Guten Morgen,

in unserem Projekt hab ich in den letzten zwei Wochen zwei Fehlermeldungen von Anwendern bekommen, die ich hier in unseren Umgebungen nicht nachvollziehen kann. Die "sporadischen" Fehler halt, die jeder Programmierer so sehr liebt. :mrgreen:

Und zwar folgendes ...
Zitat:

AdsQuery: Operation bei geschlossener Datenmenge nicht ausführbar.

Exception class: EDatabaseError
Exception address: 0048A704
------------------------------------------------------------------------------
Stack list, generated 4/02/2008 11:24:17
[0048A6FF] DB.DatabaseError + $5F
[0049688D] DB.TDataSet.CheckActive + $31
[004993B0] DB.TDataSet.CheckBrowseMode + $8
[00498B0F] DB.TDataSet.First + $B
[00617BE1] RDataModule.TDBModule.AssignSendingScheduleItems (Line 3576, "units\RDataModule.pas" + 6) + $3
[00496943] DB.TDataSet.SetActive + $77
[006181A9] RDataModule.TDBModule.GetSendingScheduleItems (Line 3693, "units\RDataModule.pas" + 21) + $C
[005B230D] RSendingManager.TSendingManager.CollectScheduleIte ms (Line 347, "units\RSendingManager.pas" + 5) + $12
[005B2F14] RSendingManager.TSendingManager.Start (Line 726, "units\RSendingManager.pas" + 22) + $3
[005BE4E7] F_SendingAssistantForm.TSendingAssistantForm.BitBt n1Click (Line 1032, "frames\F_SendingAssistantForm.pas" + 20) + $9
[004725BC] Controls.TControl.Click + $64
...
Das einzig markante ist, dass diese Anwender bereits das neueste Update haben, was wir Mitte Februar releasen wollen (haben aber auch noch ein paar mehr). Die meisten anderen Anwender haben noch eine ältere Version von Dezember. Allerdings hab ich in dem Teil des Programms in dem Zeitraum nichts weiter verändert, außer die ProgressForm da reinzupacken. Die war vorher eine "Ebene" höher (noch mit in TSendingManager).

Ist es vielleicht der zweite Zugriff auf "Query.RecordCount" in RDataModule.AssignSendingScheduleItems für "FPrgFrm.ShowProgressForm(Language.GetString(LID_L ABEL_STATUS_CREATING_OPTIMIZATION_PLAN) + ' ...', Query.RecordCount, nil, TRUE);"? (Code siehe unten) Kann ich mir aber nur schwer vorstellen ... :gruebel: ... Wie schon gesagt läuft der gleiche Spaß hier auf 4 verschiedenen Systemen blasenfrei. Auf einem Vista-Laptop laufen die Sendeaufträge sogar quasi 24/7 durch.

Ich hab bisschen gegoogelt und gelesen, dass der Fehler eigentlich nur bei Verwendung von TTable auftritt. Da ich hier aber in dem Zusammenhang keine TTable verwende (eigentlich nirgends in dem Projekt), komme ich hier nicht weiter.

Hier noch die Codes zu den Routinen CollectScheduleItems, GetSendingScheduleItems und AssignSendingScheduleItems. TSendingManager.Start aktiviert nur einen Timer, der wiederum CollectScheduleItems bei OnTimer aufruft.

Delphi-Quellcode:
procedure TSendingManager.CollectScheduleItems;
begin
  if Assigned (FOnClearHealingsheetsQue) then
    // nur Zugriff auf einen VST
    FOnClearHealingsheetsQue (Self);

  // FScheduleList-Items freigeben und FScheduleList.Clear;
  DisposeScheduleItems;

  // Sendeaufträge aus DB holen
  DBModule.GetSendingScheduleItems(TRUE, 0, FScheduleList);

  // nur Zugriff auf VST
  DisplayHealingsheetSchedule (DEFAULT_SENDING_SCHEDULE_ITEMS);
end;
Delphi-Quellcode:
function TDBModule.RemoveInactiveSendingScheduleItems: Integer;
begin
  Result := 0;
  with AdsQuery, SQL do
    try
      Clear;

      Add ('DELETE FROM SendingSchedule ' +
           'WHERE Active=FALSE');

      ExecSQL;
      Close;
      Result := 1;
    except
      on E: Exception do ThrowSQLException (SQL[0], FALSE, E);
    end;
end;

procedure TDBModule.GetSendingScheduleItems (ActiveOnly: Boolean; MaxItems: Integer; var List: TSendingScheduleList);
var
  s: String;
begin
  // Inaktive Sendeaufträge im Vorfeld löschen
  RemoveInactiveSendingScheduleItems;

  with AdsQuery, SQL do
    //try
    begin
      Clear;

      if ActiveOnly then
        s := ' WHERE Active=TRUE '
      else s := '';

      Add ('SELECT * FROM ' +
           ' SendingSchedule ' +
           s +
           ' ORDER BY ' +
           ' SendingTimestamp');

      Open;
      if (RecordCount > 0) then
        AssignSendingScheduleItems (List, AdsQuery);
      Close;
{    except // Catch von Exception ausgeschalten wg Fehlersuche
      on E: Exception do ThrowSQLException (SQL[0], FALSE, E);}
    end;
end;
Delphi-Quellcode:
procedure TDBModule.AssignSendingScheduleItems (var List: TSendingScheduleList; Query: TADSQuery);
var
  a: Integer;
  ScheduleItem: PSendingScheduleItem;
  FPrgFrm: TProgressForm;
begin
  FPrgFrm := TProgressForm.Create(nil);
  with Query do
    try
      a := 0;
      FPrgFrm.ShowProgressForm(Language.GetString(LID_LABEL_STATUS_CREATING_OPTIMIZATION_PLAN) + ' ...', Query.RecordCount, nil, TRUE);
      First; // ... entweder knallts hier ...
      try
        while not EOF do // ... oder hier ...
          begin
            FPrgFrm.UpdateProgressBar(a + 1);
            inc (a);
            ProcessMessages;

            New (ScheduleItem);

            ScheduleItem^.ID := FieldByName ('ID').AsInteger;
            ScheduleItem^.HealingsheetIndexID := FieldByName ('HealingsheetIndexID').AsInteger;
            ScheduleItem^.ClientID := FieldByName ('ClientID').AsInteger;
            ScheduleItem^.Duration := FieldByName ('Duration').AsInteger;
            ScheduleItem^.Frequency := FieldByName ('Frequency').AsInteger;
            ScheduleItem^.SendingTimestamp := FieldByName ('SendingTimestamp').AsDateTime;
            ScheduleItem^.EndingTimestamp := FieldByName ('EndingTimestamp').AsDateTime;
            ScheduleItem^.SendingType := TSendingType (Byte (FieldByName ('SendingType').AsInteger));
            ScheduleItem^.Active := FieldByName ('Active').AsBoolean;

            List.Add(ScheduleItem);

            Next;
          end;
      except
        on E: Exception do ThrowSQLException (SQL[0], FALSE, E);
      end;
    finally
      FreeAndNil (FPrgFrm);
    end;
end;
Habt ihr vielleicht noch eine Idee? :gruebel:

MrSpock 5. Feb 2008 06:42

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Hallo Nuclear-Ping,

wo öffnest du denn die Query, bevor du First und EOF aufrufst?

Nuclear-Ping 5. Feb 2008 06:44

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
In TDBModule.GetSendingScheduleItems (Code ist oben)
Delphi-Quellcode:
// ...
      Open;
      if (RecordCount > 0) then
        AssignSendingScheduleItems (List, AdsQuery);
      Close;
// ...

mkinzler 5. Feb 2008 06:49

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Aber du schließt sie ja gleich wieder.

Nuclear-Ping 5. Feb 2008 07:14

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Ja, aber erst nach dem AssignSendingScheduleItems (wenn RecordCount > 0) durchgelaufen ist. Die Ergebnisse aus der Query werden ja dort in die List übertragen und somit brauche ich die Ergebnissmenge auch nicht mehr, daher Close. Ist doch korrekt?

mashutu 5. Feb 2008 09:07

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Hmm, ich steig jetzt nicht wirklich so genau durch, was Dein Code da alles macht (arg aus dem Context gerissen) aber vielleicht solltest Du mal versuchen, die With-Konstrukte aufzuloesen.
(Nur so als Idee)

Nuclear-Ping 5. Feb 2008 09:32

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Naja, im Grunde ist nur GetSendingScheduleItems relevant.

Das macht nix anderes als eine SELECT-Query auf 'ne lokale Datenbank und schiebt die Ergebnisse dann in eine TList.

Wie schon geschrieben läuft das (auch mit dem "with-Konstrukt") hier auf 4 verschiedenen Systemen (auf einem im Dauerbetrieb) blasenfrei. Ich kann mir nicht vorstellen, dass es daran hängt. Insgesamt liegen wir glaube bei ~80 Anwendern. Aber zwei Anwender haben mir bisher von solchen sporadischen Exceptions berichtet und dem wollte ich mal auf den Grund gehen.

samson 5. Feb 2008 09:59

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Hallo,

liegt es vielleicht daran, das die Query aus welchem Grund auch immer nicht geöffnet werden konnte?

Nen: RecordCount funzt nur, wenn die Query auch geöffnet ist.

Das würde ich einbauen, mit entsprechender Untersuchung dann.

Ich habe mit RecordCount auch schon mal Probleme gehabt und habe mich dann für folgendes Konstrukt entschieden:

Delphi-Quellcode:
If (not Query.BOF) and (not Query.EOF) then
   ...
Gruß


Frank

P.S. Bei den TOraQuery von AllroundAutomations gibt es glaube ich ne Eigenschaft, wie Connected TRUE/FALSE

Nuclear-Ping 5. Feb 2008 11:39

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Danke für den Tip! :)

Das mit dem RecordCount hab ich auch im Verdacht. Hab die GetSendingScheduleItems-Prozedur erstmal so abgeändert:
Delphi-Quellcode:
procedure TDBModule.GetSendingScheduleItems (ActiveOnly: Boolean; MaxItems: Integer; var List: TSendingScheduleList);
var
  s: String;
  RecCnt: Cardinal;
begin
  RemoveInactiveSendingScheduleItems;

  with AdsQuery, SQL do
    //try
    begin
      Clear;

      if ActiveOnly then
        s := ' WHERE Active=TRUE '
      else s := '';

      Add ('SELECT * FROM ' +
           ' SendingSchedule ' +
           s +
           ' ORDER BY ' +
           ' SendingTimestamp');

      Open;
      RecCnt := RecordCount; // ** Neu ...
      if (RecCnt > 0) then
        AssignSendingScheduleItems (List, AdsQuery, RecCnt);

      Close;
{    except
      on E: Exception do ThrowSQLException (SQL[0], FALSE, E);}
    end;
end;
... und auch die AssignSendingScheduleItems Routine angepasst und einem Anwender ein Update geschickt. Mal schauen, was er die Tage sagt.

Falls es da immernoch Probleme gibt, bau ich den Vorschlag von dir mal rein.

hoika 7. Feb 2008 04:07

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Hallo,

was ich hier auf jeden Fall vermisse,
ist die Verwendung von try finally .

Delphi-Quellcode:
Query.Open;
try
  // db code
finally
  Query.Close
end;
Ausserdem halt ich meine Queries auch immer nur solange offen,
wie notwendig. Das machst du aber ja auch schon.

Beim RecordCount würde ich aber vorsichtig sein.
Je nach verwendeter DB (ADS kenne ich nicht),
liefert es entweder gar keinen Wert oder den der gefetchten Records.
Besser ist ein bei SQL-Servern ein Select Count(*).

Das RecordCount zählt z.B. unter FB (BDE, jaja ;) ) die Datensätze LOKAL
durch. Dazu müssen sie erst mal vom Server geholt werden, das dauert ...


Heiko


Heiko


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:28 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz