Delphi-PRAXiS

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

alzaimar 7. Feb 2008 06:16

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Hoika, hier wäre ein 'Select count(*)' eine Performancebremse. Besser (weil es nur darum, geht, ob überhaupt etwas zurückgekommen ist):
Delphi-Quellcode:
If Not MyQuery.IsEmpty Then ...

Nuclear-Ping 7. Feb 2008 12:58

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Ups, garnicht mitgekriegt, dass hier noch wer geantwortet hat. Sorry. ^^

Problem ist wieder aufgetaucht, diesmal aber auf der Testmaschine im Büro (... mit dem geänderten RecordCount) ... :wall: ... Ich kapiers nicht ... Vorallem wenn du dazu nen Projektleiter am Ohr hast, der erklärt haben will, warum das aufeinmal nicht mehr geht. :oops:

Ich verbau mal noch eure anderen Vorschläge (bis auf Select count(*) ^^) und dann mal schauen.

[edit]
@hoika: try/except war drum, hab ich nur auskommentiert, weil vorher eine eigene Meldung kam wie
Code:
----------------
Fehler bei SQL Abfrage:
<leer>

SQL:
SELECT * FROM SendingSchedule ...

---- [ OK ] ----
Nun kommt stattdessen die Meldung mit der geschlossenen Datenmenge.
[/edit]

[nochmal edit]
@samson:
Delphi-Quellcode:
If (not Query.BOF) and (not Query.EOF) then
  ...
Versuch das grad zu verstehen ... then was? Wenn ich das unter das Open packe, ergibts FALSE, weil's wahrscheinlich BOF && !EOF ist. Kapier das nicht. ^^
[/nochmal edit]

mikhal 7. Feb 2008 16:33

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Mach aus
Delphi-Quellcode:
If (not Query.BOF) and (not Query.EOF) then
mal
Delphi-Quellcode:
If not Query.IsEmpty then
, macht das Gleiche.

Grüße
Mikhal

Nuclear-Ping 7. Feb 2008 17:01

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Ok. Hab das jetzt so gemacht:
Delphi-Quellcode:
Open;
RecCnt := RecordCount;
if (RecCnt > 0) and (not IsEmpty) and Active then
  AssignSendingScheduleItems (List, AdsQuery, RecCnt);
Close;
... mal schauen, ob's immernoch knallt.

hoika 7. Feb 2008 17:52

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

und wieder kein try finally ...


Heiko

mikhal 7. Feb 2008 19:31

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Delphi-Quellcode:
(RecCnt > 0)
ist das Gleiche wie
Delphi-Quellcode:
(not IsEmpty)
Grüße
Mikhal

DeddyH 7. Feb 2008 19:54

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Klingt irgendwie logisch ;)

Union 7. Feb 2008 20:09

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Ich würde folgendes versuchen:
  • 1. AdsQuery.Sequenced := True;
    2. Processmessages in der Schleife durch Update der benötigten Komponenten ersetzen
    3. Die ganze Progress-Geschichte über einen Callback aufrufen lassen und nicht in die Schleifen integrieren
und dann prüfe mal, ob der Fehler beim ersten Durchlauf der while Schleife auftritt oder erst bei einem der folgenden (a > 0).

Des weiteren sehe ich solche Bemerkungen wie "try deaktiviert zur Fehlernachverfolgung". Bau doch mal MadExcept oder EurekaLog ein. Dann kannst Du auch vom Kunden qualifizierte Fehlerberichte erhalten, evtl. sogar automatisch per E-Mail. Und die mehrfachen with machen ein vernünftiges Debugging auch nicht gerade zum Kinderspiel.

Nuclear-Ping 7. Feb 2008 21:46

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
Zitat:

Zitat von Union
Ich würde folgendes versuchen:
  • 1. AdsQuery.Sequenced := True;
    2. Processmessages in der Schleife durch Update der benötigten Komponenten ersetzen
    3. Die ganze Progress-Geschichte über einen Callback aufrufen lassen und nicht in die Schleifen integrieren
und dann prüfe mal, ob der Fehler beim ersten Durchlauf der while Schleife auftritt oder erst bei einem der folgenden (a > 0).

Des weiteren sehe ich solche Bemerkungen wie "try deaktiviert zur Fehlernachverfolgung". Bau doch mal MadExcept oder EurekaLog ein. Dann kannst Du auch vom Kunden qualifizierte Fehlerberichte erhalten, evtl. sogar automatisch per E-Mail. Und die mehrfachen with machen ein vernünftiges Debugging auch nicht gerade zum Kinderspiel.

Hm, dass die ProcessMessages da drin das Problem verursachen können kann auch sein. Werd ich als nächstes versuchen, wenn das immernoch auftritt. Danke für den Hinweis! :)

Und wie schon gesagt: Das ist kein Fehler der immer auftritt, sondern nur manchmal, bei Vollmond oder was weiß ich. Ich kann ihn hier nichtmal reproduzieren.

Bzgl. Fehlerreporting benutze ich bereits von JEDI die Exception-Dialoge. Sieht man ja auch im ersten Post. Ich hab den Try-Except-Block da nur auskommentiert, weil vorher eine nichtssagende Fehlermeldung kam.

Nuclear-Ping 8. Feb 2008 11:24

Re: Operation bei geschlossener Datenmenge nicht ausführbar
 
[edit]
Schwachsinn ^^
[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:22 Uhr.

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