Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Stack Überlauf fehler (https://www.delphipraxis.net/177849-stack-ueberlauf-fehler.html)

Drumbo 1. Dez 2013 10:56

Datenbank: SQL Server 2012 • Version: 11 • Zugriff über: XE 3

Stack Überlauf fehler
 
Guten Morgen,

ich habe vor, dass in meinem DBGrid sobald sich irgendwas in diesem Tut, eine Prozedure aufgerufen wird.
Diese Procedure greift auf die mit dem DBGrid verknüpfte Datenbank zu und durchläuft diese.
Es soll geguckt werden, ob in dem speziellen Datensatz der Artikel bestellt ist oder nicht. In der Datenbank wird existiert dafür ein Boolisches Feld. Die Prozedur sieht wir folgt aus:
Delphi-Quellcode:
procedure TAuftrag_form.BestellbtnCreate();
var
i:integer;
begin

   i:=1;
   Ersatzteil_Dataset.First;
while not Ersatzteil_Dataset.Eof do
  begin

    if Ersatzteil_DatasetBestellt.Value=True then
    begin
      DBAdvGrid4.RemoveButton(7,DBAdvGrid4.Row);
    end;
     Ersatzteil_Dataset.Next;
  end;

 Ersatzteil_Dataset.first;

while not Ersatzteil_Dataset.Eof do
  begin

  if Ersatzteil_DatasetBestellt.Value=False then
    begin
      DBAdvGrid4.AddButton(7,DBAdvGrid4.Row,50,15,'Bestellen',TCellHAlign(2),TCellVAlign(2));
    end;
  Ersatzteil_Dataset.Next;
  end;

end;
Da sich die Daten in dem Grid ändern und somit evtl. auch der Bestell Status muss immer erst geschaut werden ob der Button gezeichnet werden muss oder eben nicht.

Wen ich mir die Prozedur auf einen Knopf lege ist alles inordnung.
Möchte ich allerdings diese Prozedur in der Datasource beim OnChange aufrufen stürzt das Programm immer ab und gibt die Meldung "Stack Überlauf".
Ich könnte mir vorstellen, dass die Datasource noch nicht bereit ist oder noch irgendwelche Aufgaben erledigen muss aber wie kann ich Abfragen ob dem so ist?
Bzw. wie kann ich generell dieses Problem lösen?
Gruß Chris

DeddyH 1. Dez 2013 11:00

AW: Stack Überlauf fehler
 
Du meinst vermutlich TDatasource.OnDataChange? Das wird auch ausgelöst, wenn sich der aktive Datensatz ändert. Da Du die Datenmenge durchläufst, wird das also ausgelöst, durchläuft die Datenmenge, wird wieder ausgelöst und durchläuft die Datenmenge etc. pp.

himitsu 1. Dez 2013 11:03

AW: Stack Überlauf fehler
 
Rate mal, was OnChange OnDataChange macht, wenn deine Funktion anfängt durch das DataSet zu Scrollen?

Tipp: Haltepunkt auf den Start deiner Funktion und dann schön mit F7 durchsteppen.



PS:
Zitat:

Delphi-Quellcode:
if Ersatzteil_DatasetBestellt.Value=True then

Lass' diese Vergleiche mit True und False
und verwende
Delphi-Quellcode:
if x then
und
Delphi-Quellcode:
if not x then
.




Reicht es nicht, wenn du nur einmal durchscrollst und in einem durchgang die Buttons hinzufügst?
Oder müssen die unbedingt nacheinander sein.

Perlsau 1. Dez 2013 11:51

AW: Stack Überlauf fehler
 
Da ist offenbar vieles im Argen:

1. Man prüft Boolsche Ausdrücke nicht auf True! Eine Abfrage, ob ein Ausdruck wahr oder falsch ist, sieht folgendermaßen aus:
Delphi-Quellcode:
  if Ersatzteil_DatasetBestellt.Value then
  begin
    TuDiesUndDas;
    TuDasAuchNoch;
  end else
  begin
    TuWasAnderes;
    TuNochWasAnderes;
  end;
2. Mit diesem Konstrukt ist es nun auch nicht mehr nötig, die ganze Tabelle zweimal zu durchlaufen, da ein Boolean-Wert entweder wahr oder falsch ist und für beide Fälle entsprechende Methoden bereitgestellt werden.

3. Wenn du eine Ereignisbehandlung schreibst, in der das Ereignis, für das du diese Procedure schreibst, aufgerufen werden kann, ohne daß eine Abbruchbedingung definiert wurde, mußt du dich nicht wundern, wenn das einen Stack-Überlauf zur Folge hat. Recursive Programmierung erfordert also immer eine Abbruchbedingung.

4. Was möchtest du wirklich erreichen?

Offenbar hast du ein DBGrid, das eine Tabelle mit Artikeln darstellt. Nun möchtest du jedesmal, wenn der Anwender einen Datensatz selektiert, prüfen, ob für diesen Artikel eine Bestellung vorliegt (wozu auch immer). Liegt keine Bestellung vor, soll, wie ich das verstanden habe, ein Button sichtbar werden, mit dem man eine solche Bestellung vornehmen kann. Und diesen Button möchtest du, wie es scheint, in einer Spalte des DBGrids erscheinen lassen? Wieso eigentlich?

Ich würde hier einen Button unterhalb oder neben dem DBGrid platzieren, der je nach Zustand der entsprechenden Spalte (Value?) enabled oder disabled ist. In der Ereignisbehandlungsmethode AfterScroll deines Datasets löst du nun ein Ereignis aus, das den betreffenden Button je nach Zustand der entsprechenden Spalte auf verfügbar (enabled := true) oder nicht verfügbar setzt.

Es ist also nicht notwendig, beim Wechseln des Datensatz-Zeigers jedesmal die ganze Tabelle zu durchlaufen, denn du möchtest ja nur diesen einen Datensatz überprüfen.

Drumbo 2. Dez 2013 05:46

AW: Stack Überlauf fehler
 
Morgen und danke für die Antworten.

Ja war bisschen schlampig implementiert. Ja hab auch das onDataChange Ereignis gemeint. Sorry für die ungenauigkeit, kommt nicht mehr vor.


Zu der Logik bzw. Notwendigkeit des mehrmaligen Durchlaufen dieser Datenbank:

Ich habe verschieden Geräte bzw. Reparaturen denen ich verschiedene Ersatzteile hinzufügen möchte aber auch löschen. Desweiteren kann man innerhalb dieses Forms zu anderen Geräten bzw. Reparaturaufträgen scrollen. Ich hatte halt die Idee die Knöpfe immer dann zu zeichenen (bzw. löschen) wenn sich was ändert. Ich könnte jetzt auch alle Eventualitäten und möglichen Triggerzeitpunkte raussuchen und dort dann überprüfen ob die Knöpfe gezeichnet werden müssen oder nicht. Fände es aber beim OnDataChange besser.
Das mit dem Rekursiven aufruf leuchtet ein.
Hab jetzt eine Wartemarke erstellt und blocke den Zugriff während die Datenbank durchlaufen wird.

Danke für die schnelle und gute Hilfe.
Zur Komplettierung hier nochmal der ordentliche Code:wink:
Delphi-Quellcode:
procedure TAuftrag_form.BestellbtnCreate();
var
i:integer;
begin
  busy :=true;

   Ersatzteil_Dataset.First;
while not Ersatzteil_Dataset.Eof do
  begin
    if Ersatzteil_DatasetBestellt.Value then
    begin
      DBAdvGrid4.RemoveButton(7,DBAdvGrid4.Row);
    end else
    begin
      DBAdvGrid4.AddButton(7,DBAdvGrid4.Row,50,15,'Bestellen',TCellHAlign(2),TCellVAlign(2));
    end;
     Ersatzteil_Dataset.Next;
  end;

  busy:=false;

end;

Furtbichler 2. Dez 2013 06:22

AW: Stack Überlauf fehler
 
Ah, die Buttons sind in jeder Zeile des Ersatzteil-Grids...
So kann man das auch lösen. So wie Persau das gelöst hat, ist es aber einfacher.

Also: Dein Ersatzteil-Grid und dadrunter/drüber/neben ein (1!) Button 'btBestellen'.

Im OnDataChange-Ereignis des ErsatzTeil-Datasets dann:
Delphi-Quellcode:
Procedure TMyForm.ErsartTeilSourceDataChange(Sender: TObject; Field: TField);
Begin
  if Field=nil then
    btBestellen.Enabled := Not Ersatzteil_DatasetBestellt.AsBoolean;
End;
Fertig.
Wenn Field=nil, dann wird die Zeile gewechselt. Der Button verändert seinen Status also genau dann, wenn eine neue Zeile im Grid ausgewählt wird und ist ausgegraut, wenn man das Teil nicht bestellen kann (weil schon bestellt) und normal, also drückbar, wenn nicht.

Die Tatsache, das ein Ersatzteil schon bestellt ist, visualisierst Du entweder, indem Du die Spalte 'Bestellt' als Checkbox anzeigst, oder aber, indem Du die ganze Zeile einfärbst (z.B. grün=bestellt). Das spart Platz, denn die Information 'bestellt' erkennt man nun direkt an der Farbe.

Drumbo 2. Dez 2013 09:06

AW: Stack Überlauf fehler
 
Wollte die Tatsache das das Ersatzteil bestellt ist eigentlich dadurch visualisieren das der Button verschwindet. Sprich man bestellt und der Button geht weg. An sich funktioniert das mit der while auch ganz gut. Hab halt nun das Problem, dass ich durch die Schleife immer an den letzten Datensatz springe. Das wiederum ist schön und gut wenn ich aus dem Grid rausbleibe und die Datasource quasi nicht veränder. TU ich dies jedoch zeigt das Grid mir nur noch unvollständige Ergebnisse an. Das liegt daran, dass ich den Datenbank Zeiger ja verschiebe und damit dann das OnDataChange auslöse. Jetzt stell ich mir die Frage ob es hilft, wenn ich in meiner bestellbtncreate procedure den aktuellen Zeiger Speicher und nachher zurück setze? Könnt ihr mir das sagen bzw. Wie Kriege ich den überhaupt gespeichert?
@ Furtbichler: überprüft deine procedur immer den aktuell geänderten Datensatz oder wie geht das

DeddyH 2. Dez 2013 09:18

AW: Stack Überlauf fehler
 
Ich habe es zwar nicht ganz verstanden, aber den aktuellen Datensatzzeiger kannst Du Dir mit Delphi-Referenz durchsuchenGetBookmark merken und mit Delphi-Referenz durchsuchenGotoBookmark wieder dorthin zurückkehren, sofern es sich nicht um eine unidirektionale Datenmenge handelt.

p80286 2. Dez 2013 12:34

AW: Stack Überlauf fehler
 
Zitat:

Zitat von Drumbo (Beitrag 1238144)
Wollte die Tatsache das das Ersatzteil bestellt ist eigentlich dadurch visualisieren das der Button verschwindet. Sprich man bestellt und der Button geht weg.
....
An sich funktioniert das mit der while auch ganz gut. Hab halt nun das Problem, dass ich durch die Schleife immer an den letzten Datensatz springe. Das wiederum ist schön und gut wenn ich aus dem Grid rausbleibe und die Datasource quasi nicht veränder. TU ich dies jedoch zeigt das Grid mir nur noch unvollständige Ergebnisse an. Das liegt daran, dass ich den Datenbank Zeiger ja verschiebe und damit dann das OnDataChange auslöse. Jetzt stell ich mir die Frage ob es hilft, wenn ich in meiner bestellbtncreate procedure den aktuellen Zeiger Speicher und nachher zurück setze? Könnt ihr mir das sagen bzw. Wie Kriege ich den überhaupt gespeichert?

Ich würde das im Prinzip so lösen, daß eine Bestellung (Update / Insert ..) an die Db geschickt wird und mit einem anschließenden Select werden die (hoffentlich) geänderten Daten zurück geholt.
Die Klimmzüge auf dem Client mögen zwar schön sein, sind meiner Meinung nach nicht zuverlässig und unnötig kompliziert.

Gruß
K-H

Perlsau 2. Dez 2013 15:24

AW: Stack Überlauf fehler
 
Zitat:

Zitat von p80286 (Beitrag 1238175)
... und mit einem anschließenden Select werden die (hoffentlich) geänderten Daten zurück geholt.

Ich weiß ja nicht, wie du das siehst, aber ich denke, daß Programme, die auf Hoffnung basieren, nicht wirklich gelungen sind :twisted:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:10 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