Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi MyBase: Datenlöschen (https://www.delphipraxis.net/181462-mybase-datenloeschen.html)

Kralle 18. Aug 2014 10:42

Datenbank: MyBase • Version: x • Zugriff über: x

MyBase: Datenlöschen
 
Moin,

entweder sehe ich den Wald vor lauter Bäumen nicht oder bin total auf dem Holzweg.

Gebene ist folgender Code:
Code:
begin
   BtDatensatzLoeschen.Caption:=IntToStr(ClientDataSet1.RecordCount); // Anzahl der Einträge in der Datenbank
   for I := 1 to ClientDataSet1.RecordCount do
     Begin
       If ClientDataSet1.Locate('Codenummer',lbledt1.text,[]) then // Datensatz finden
         begin
          ClientDataSet1.edit; // Datenbank zum Bearbeiten öffnen
           ClientDataSet1.delete; // Datensatz löschen
           ClientDataSet1.Post; // Datenbank aktualisieren
         end;
     End;
end;

procedure TForm1.BtStatusAendernClick(Sender: TObject);
begin
   If ClientDataSet1.Locate('ID','3',[]) then // Datensatz finden
     if ClientDataSet1['Status'] ='0' then
       begin
         ClientDataSet1.edit; // Datenbank zum Bearbeiten öffnen
         ClientDataSet1['Status']:='1'; // Inhalt ändern
         ClientDataSet1.Post; // Datenbank aktualisieren
       end
     else
     begin
         ClientDataSet1.edit; // Datenbank zum Bearbeiten öffnen
         ClientDataSet1['Status']:='0'; // Inhalt ändern
         ClientDataSet1.Post; // Datenbank aktualisieren
     end;
 end;
Der untere Teil funktioniert wie gewünscht, aber der obere Teil führt zur folgenden Fehlermeldung:
Zitat:

Erste Gelegenheit für Exception bei $00007FFA23B25BF8. Exception-Klasse EDatabaseError mit Meldung 'ClientDataSet1: Datenmenge weder im Editier- noch im Einfügemodus'. Prozess mybase_test.exe (404)
Aber, ich habe doch ein
Code:
ClientDataSet1.edit; // Datenbank zum Bearbeiten öffnen
im Code.
Was mache ich falsch??

Gruß Heiko

Jasocul 18. Aug 2014 11:03

AW: MyBase: Datenlöschen
 
Benutze zukünftig den Debugger, damit du siehst, wo der Fehler passiert. Vielleicht wärest du dann selbst auf die richtige Idee gekommen.

Der Fehler dürfte durch dein "ClientDataSet1.Post" entstehen.

Das ClientDataSet1.Edit ist völlig überflüssig. Du setzt damit den Datensatz, den du löschen willst in den Edit-Modus. Danach löscht du diesen dann. Ich wäre nicht mal auf die Idee gekommen, das so zu machen und hätte eher vermutet, dass dort eine Exception auftritt.

Und für ClientDataSet1.Delete benötigst du kein ClientDataSet1.Post. Das Post ist nur für neue Datensätze oder Datensätze, die geändert werden.

Kralle 18. Aug 2014 11:50

AW: MyBase: Datenlöschen
 
Hallo Jasocul,

Zitat:

Zitat von Jasocul (Beitrag 1268931)
Benutze zukünftig den Debugger, damit du siehst, wo der Fehler passiert. Vielleicht wärest du dann selbst auf die richtige Idee gekommen.

Als ich versucht habe mittels Breakpoint und F7 durch den Quellcode zu laufen um zu sehen wo der Fehler genau auftritt, fuktionierte das natürlich mal wieder nicht.
Zitat:

Zitat von Jasocul (Beitrag 1268931)
Der Fehler dürfte durch dein "ClientDataSet1.Post" entstehen.

Jupp, das war es.
Zitat:

Zitat von Jasocul (Beitrag 1268931)
Das ClientDataSet1.Edit ist völlig überflüssig. Du setzt damit den Datensatz, den du löschen willst in den Edit-Modus. Danach löscht du diesen dann. Ich wäre nicht mal auf die Idee gekommen, das so zu machen und hätte eher vermutet, dass dort eine Exception auftritt.

Da ein Schrittweises abarbeiten mal wieder nicht funktioniert hat und es in der Fehlermeldung hies:
Zitat:

Datenmenge weder im Editier- noch im Einfügemodus'
dachte ich mir:"Da haste wohl das "Edit" vergessen."
Zitat:

Zitat von Jasocul (Beitrag 1268931)
Und für ClientDataSet1.Delete benötigst du kein ClientDataSet1.Post. Das Post ist nur für neue Datensätze oder Datensätze, die geändert werden.

okay, das habe ich mir jetzt notiert.

Danke.

Gruß HEiko

Jumpy 18. Aug 2014 11:54

AW: MyBase: Datenlöschen
 
Ich verstehe nur nicht ganz, warum du für das Löschen eines Datensatzes in einer Schleife durch die ganze Datenmenge läufst? Dafür hast du doch Locate?

Kralle 18. Aug 2014 11:58

AW: MyBase: Datenlöschen
 
Moin,

Zitat:

Zitat von Jumpy (Beitrag 1268949)
Ich verstehe nur nicht ganz, warum du für das Löschen eines Datensatzes in einer Schleife durch die ganze Datenmenge läufst? Dafür hast du doch Locate?

Ich will aber nicht nur einen Datensatz löschen sondern alle mit einem bestimmten Wert in "Codenummer".

Gruß HEiko

mkinzler 18. Aug 2014 12:02

AW: MyBase: Datenlöschen
 
Trotzdem kannst Du dich dann auf die Datensätze, die dem Suchmuster entsprechen, beschränken (Z.B. per Locate)

Jumpy 18. Aug 2014 12:03

AW: MyBase: Datenlöschen
 
ok. Dann würde ich aber mit einer while Schleife arbeiten:

while ClientDataset1.Locate(...) do
ClientDataset1.Delete

oder so.

Oder natürlich ein entsprechendes SQL-Statement absetzen (um alle entsprehcende Datensätze auf einmal zu löschen) und danach das ClientDataset aktualisieren.

DeddyH 18. Aug 2014 12:04

AW: MyBase: Datenlöschen
 
Das würde ich vielleicht eher so angehen (Pseudo-Code):
Delphi-Quellcode:
Dataset.First;
while not Dataset.EOF do
  begin
    if Dataset.FieldByName['Codenummer'] = DeinSuchbegriff then
      Dataset.Delete
    else
      Dataset.Next;
  end;
SQL o.ä. scheidet bei MyBase ja leider aus.

Jumpy 18. Aug 2014 12:17

AW: MyBase: Datenlöschen
 
Zitat:

Zitat von DeddyH (Beitrag 1268954)
SQL o.ä. scheidet bei MyBase ja leider aus.

Das wußte ich nicht und nehme meinen obigen Vorschlag wieder zurück. :oops:

Kralle 18. Aug 2014 12:52

AW: MyBase: Datenlöschen
 
Danke, für Eure Hilfe.

Die "Schleife " habe ich jetzt so gelöst:
Code:
with ClientDataSet1 do
   begin
     First;
     while not EOF do
       begin
         if FieldByName('Codenummer').AsString = lbledt1.text then
           Delete
         else
           Next;
       end;
   end;
Oder spricht was gehen "with"?

Gruß Heiko

mkinzler 18. Aug 2014 12:57

AW: MyBase: Datenlöschen
 
Wenn Du Dir ganz sicher bist, dass niemand jemals auf die Idee kommt, einem Formular First/Next/Delete Eigenschaften/Methoden zu spendieren.

Kralle 18. Aug 2014 13:38

AW: MyBase: Datenlöschen
 
Moin,

Zitat:

Zitat von mkinzler (Beitrag 1268968)
Wenn Du Dir ganz sicher bist, dass niemand jemals auf die Idee kommt, einem Formular First/Next/Delete Eigenschaften/Methoden zu spendieren.

:?::?::?:
Selbst Wenn jemand dem Formular diese Eigenschaften zufügen würde, würde das "with" nicht dafür sorgen, das "first" und "next" sich auf das "ClientDataSet1" beziehen?
Oder würden sich die Eigenschaften dann auf trotzdem auf das Formular beziehen?

Gruß HEiko

DeddyH 18. Aug 2014 13:59

AW: MyBase: Datenlöschen
 
With nutzt immer den "innersten" Scope, d.h. in Deinem Fall sollte es keine Probleme geben. Trotzdem lauern da Fallstricke, die sich u.U. nur sehr schwer finden lassen, so dass einige User (mich eingeschlossen) von der Benutzung von with abraten.

Kralle 18. Aug 2014 14:03

AW: MyBase: Datenlöschen
 
Hallo,
Zitat:

Zitat von DeddyH (Beitrag 1268977)
With nutzt immer den "innersten" Scope, d.h. in Deinem Fall sollte es keine Probleme geben. Trotzdem lauern da Fallstricke, die sich u.U. nur sehr schwer finden lassen, so dass einige User (mich eingeschlossen) von der Benutzung von with abraten.

also doch lieber die Variante mit "ClientDataSet1." - richtig?

Gruß Heiko

DeddyH 18. Aug 2014 14:06

AW: MyBase: Datenlöschen
 
Damit bist Du zumindest auf der sicheren Seite. Falls es Dir nur um Tipparbeit geht: da kann man auch mit einer Variablen (parallel zu einer vernünftigen Komponentenbenennung) einsparen, z.B.:
Delphi-Quellcode:
var
  CDS: TClientDataset;
begin
  CDS := ClientDataset1;
  CDS.First;
  //usw.

Kralle 18. Aug 2014 14:31

AW: MyBase: Datenlöschen
 
Hallo,

Zitat:

Zitat von DeddyH (Beitrag 1268980)
Damit bist Du zumindest auf der sicheren Seite.

In Ordnung. Habe ich mir notiert.

Zitat:

Zitat von DeddyH (Beitrag 1268980)
Falls es Dir nur um Tipparbeit geht: da kann man auch mit einer Variablen einsparen, z.B.:
Delphi-Quellcode:
var
  CDS: TClientDataset;
begin
  CDS := ClientDataset1;
  CDS.First;
  //usw.

Das ich auch einfach für ein ClientDataSet ein Variable definieren kann, war mir nicht bewusst.
Ich habe wieder was gelernt.

Zitat:

Zitat von DeddyH (Beitrag 1268980)
(parallel zu einer vernünftigen Komponentenbenennung) einsparen, z.B.:

Die einzigen Komponenten auf de Du hier schliessen kannst, sind TForm1 und lbledt1.
Erstere ist noch unbenannt und zweitere hat seinen Namen durch das "CnPack" erhalten.
Beide Namen sagen mir auch nicht zu, aber da es in diesem Fall nur um ein kleines Testprogramm ging, war mir das egal.

Gruß HEiko

Dejan Vu 19. Aug 2014 08:33

AW: MyBase: Datenlöschen
 
Zitat:

Zitat von DeddyH (Beitrag 1268977)
Trotzdem lauern da Fallstricke, ... von der Benutzung von 'with' abraten.

Der imho einzige nervende Fallstrick ist der, das man den Debugger nicht verwenden kann. Böse und schwer zu findende Fehler hatte ich noch keine. Aber da man den Debugger nicht verwenden kann und 'with' auch keinen Mehrwert bringt, kann (und sollte) man getrost darauf verzichten. Aber da hat so jeder seine eigenen Erfahrungen.

DeddyH 19. Aug 2014 09:48

AW: MyBase: Datenlöschen
 
Es gehört zwar nicht mehr zum Thema, aber mal ein ganz simples Beispiel:
Delphi-Quellcode:
type
  TUsedClass = class
  strict private
    FProp1: integer;
  public
    property Prop1: integer read FProp1 write FProp1;
  end;

  TUserClass = class
  strict private
    FProp2: integer;
  public
    procedure DoSomeWork;
    property Prop2: integer read FProp2 write FProp2;
  end;

{ TUserClass }

procedure TUserClass.DoSomeWork;
var
  UsedClass: TUsedClass;
begin
  UsedClass := TUsedClass.Create;
  try
    UsedClass.Prop1 := 42;
    with UsedClass do
      Prop2 := Prop1;
    ShowMessage(IntToStr(Prop2));
  finally
    UsedClass.Free;
  end;
end;
Delphi-Quellcode:
procedure TFormTest.btnTestClick(Sender: TObject);
begin
  with TUserClass.Create do
    try
      DoSomeWork;
    finally
      Free;
    end;
end;
Ausgabe: 42, also wie erwartet. Nun stellen wir uns vor, die TUsedClass ist eine gekaufte Klasse/Komponente, und wir spielen uns ein Update ein:
Delphi-Quellcode:
type
  TUsedClass = class
  strict private
    FProp1: integer;
    FProp2: integer;
  public
    property Prop1: integer read FProp1 write FProp1;
    property Prop2: integer read FProp2 write FProp2;
  end;
Was wir denn jetzt ausgegeben, wenn wir den Button anklicken? Gut, man könnte überall, wo die eigene Instanz gemeint ist, vorsichtshalber ein "self." davorschreiben, aber dann ist der Hauptgrund für das with (weniger Tipparbeit) ja auch irgendwie wieder hinfällig.

Uwe Raabe 19. Aug 2014 11:23

AW: MyBase: Datenlöschen
 
Du könntest auch einen Filter auf das ClientDataSet legen. Dann würde sich die Schleife etwas verkürzen lassen:

Delphi-Quellcode:
  cds.Filter := 'Codenummer = ' + QuotedStr(lbledt1.text); // Wenn Codenummer ein numerisches Feld ist, kann man die Quotes weglassen.
  cds.Filtered := true;
  cds.First;
  while not cds.EOF do
    cds.Delete;
  cds.Filtered := false;

Dejan Vu 19. Aug 2014 12:08

AW: MyBase: Datenlöschen
 
@DeddyH: Man kann vieles konstruieren. Nach bald 35 Jahren programmieren und davon ca. 30 mit Pascal und 'WITH' hatte ich den Fall noch nie. Kann sein, das andere täglich damit zu kämpfen haben, aber ich eben noch nicht.

Mir ist das nur irgendwann zu blöd geworden, die WITH-Dinger nicht mehr so leicht debuggen zu können. Seiteneffekte, wie sie von den Delphi-Gurus immer wieder beschworen werden, hatte ich nicht ein einziges Mal. Gehirnkrämpfe, weil man irgendwann nicht mehr weiß, zu welcher Instanz die gewith'ste Property/Methode denn nun gehört, ständig. Aber seit dem ich die Clean-Code-Pillen nehme (ja, auch die mit den Mustern oben drauf :lol: ) passiert mir das nicht mehr.

Zurück zum Thema: Ist beim Filtern eine Optimierung eingebaut oder wird die Tabelle nach dem 'Delete' komplett neu gefiltert (wäre ja eigentlich überflüssig)? Es wäre denkbar, das auch bei einem Locate ein 'DELETE' eine Positionierung des Datensatzzeigers auf den Anfang durchgeführt wird. Wenn dem so wäre, wäre die native Methode (1x durchrennen und alles Passende wegschmeißen) vielleicht doch die schnellste Variante?

DeddyH 19. Aug 2014 13:06

AW: MyBase: Datenlöschen
 
So konstruiert war das doch auch wieder nicht. Und ich wollte nur zeigen, dass man mit Effekten aus Richtungen rechnen muss, die man gar nicht auf dem Schirm hatte ;)

Uwe Raabe 19. Aug 2014 14:07

AW: MyBase: Datenlöschen
 
Zitat:

Zitat von DeddyH (Beitrag 1269069)
So konstruiert war das doch auch wieder nicht. Und ich wollte nur zeigen, dass man mit Effekten aus Richtungen rechnen muss, die man gar nicht auf dem Schirm hatte ;)

Klassisches Beispiel ist die Einführung der Eigenschaften Width und Height in TRect. Dadurch funktionierte z.B. folgender Block nicht mehr richtig:
Delphi-Quellcode:
with Rect do begin
  Left := (Width - 100) div 2;
  Top := (Height - 100) div 2;
end;
Tools wie der Pascal Analyzer von Peganza weisen einen aber dann doch auf solche Fälle hin.


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

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